diff --git a/.claude/skills/pest-testing/SKILL.md b/.claude/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.claude/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.claude/skills/tailwindcss-development/SKILL.md b/.claude/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.claude/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/.codex/skills/pest-testing/SKILL.md b/.codex/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.codex/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.codex/skills/tailwindcss-development/SKILL.md b/.codex/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.codex/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 00000000..8c6715a1 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.cursor/rules/laravel-boost.mdc b/.cursor/rules/laravel-boost.mdc new file mode 100644 index 00000000..bb7611fb --- /dev/null +++ b/.cursor/rules/laravel-boost.mdc @@ -0,0 +1,380 @@ +--- +alwaysApply: true +--- + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/.cursor/skills/pest-testing/SKILL.md b/.cursor/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.cursor/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.cursor/skills/tailwindcss-development/SKILL.md b/.cursor/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.cursor/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/.gemini/settings.json b/.gemini/settings.json new file mode 100644 index 00000000..8c6715a1 --- /dev/null +++ b/.gemini/settings.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.gemini/skills/pest-testing/SKILL.md b/.gemini/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.gemini/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.gemini/skills/tailwindcss-development/SKILL.md b/.gemini/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.gemini/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..4b217a09 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,377 @@ + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/.github/copilot/skills/pest-testing/SKILL.md b/.github/copilot/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.github/copilot/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.github/copilot/skills/tailwindcss-development/SKILL.md b/.github/copilot/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.github/copilot/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/.gitignore b/.gitignore index 69085726..6d80afa7 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,9 @@ npm-debug.log phpunit.xml yarn-error.log .DS_Store +/.junie/ +/.opencode/ +/.gemini/ +/.cursor/ +/.codex/ +/.claude/ diff --git a/.junie/guidelines.md b/.junie/guidelines.md new file mode 100644 index 00000000..4b217a09 --- /dev/null +++ b/.junie/guidelines.md @@ -0,0 +1,377 @@ + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/.junie/mcp/mcp.json b/.junie/mcp/mcp.json new file mode 100644 index 00000000..d0a44c2e --- /dev/null +++ b/.junie/mcp/mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "/opt/homebrew/Cellar/php@8.4/8.4.16_1/bin/php", + "args": [ + "/Users/gheorghelupu/code4ro/sunrise/artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 00000000..8c6715a1 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.opencode/skills/pest-testing/SKILL.md b/.opencode/skills/pest-testing/SKILL.md new file mode 100644 index 00000000..4f30ead3 --- /dev/null +++ b/.opencode/skills/pest-testing/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pest-testing +description: >- + Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature + tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, + working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, + coverage, or needs to verify functionality works. +--- + +# Pest Testing 3 + +## When to Apply + +Activate this skill when: +- Creating new tests (unit or feature) +- Modifying existing tests +- Debugging test failures +- Working with datasets, mocking, or test organization +- Writing architecture tests + +## Documentation + +Use `search-docs` for detailed Pest 3 patterns and documentation. + +## Basic Usage + +### Creating Tests + +All tests must be written using Pest. Use `php artisan make:test --pest {name}`. + +### Test Organization + +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Do NOT remove tests without approval - these are core application code. +- Test happy paths, failure paths, and edge cases. + +### Basic Test Structure + + + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + + +### Running Tests + +- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. +- Run all tests: `php artisan test --compact`. +- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. + +## Assertions + +Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: + + + +it('returns all', function () { + $this->postJson('/api/docs', [])->assertSuccessful(); +}); + + + +| Use | Instead of | +|-----|------------| +| `assertSuccessful()` | `assertStatus(200)` | +| `assertNotFound()` | `assertStatus(404)` | +| `assertForbidden()` | `assertStatus(403)` | + +## Mocking + +Import mock function before use: `use function Pest\Laravel\mock;` + +## Datasets + +Use datasets for repetitive tests (validation rules, etc.): + + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +## Pest 3 Features + +### Architecture Testing + +Pest 3 includes architecture testing to enforce code conventions: + + + +arch('controllers') + ->expect('App\Http\Controllers') + ->toExtendNothing() + ->toHaveSuffix('Controller'); + +arch('models') + ->expect('App\Models') + ->toExtend('Illuminate\Database\Eloquent\Model'); + +arch('no debugging') + ->expect(['dd', 'dump', 'ray']) + ->not->toBeUsed(); + + + +### Type Coverage + +Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag. + +## Common Pitfalls + +- Not importing `use function Pest\Laravel\mock;` before using mock +- Using `assertStatus(200)` instead of `assertSuccessful()` +- Forgetting datasets for repetitive validation tests +- Deleting tests without approval \ No newline at end of file diff --git a/.opencode/skills/tailwindcss-development/SKILL.md b/.opencode/skills/tailwindcss-development/SKILL.md new file mode 100644 index 00000000..12bd896b --- /dev/null +++ b/.opencode/skills/tailwindcss-development/SKILL.md @@ -0,0 +1,124 @@ +--- +name: tailwindcss-development +description: >- + Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, + working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, + typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, + hero section, cards, buttons, or any visual/UI changes. +--- + +# Tailwind CSS Development + +## When to Apply + +Activate this skill when: + +- Adding styles to components or pages +- Working with responsive design +- Implementing dark mode +- Extracting repeated patterns into components +- Debugging spacing or layout issues + +## Documentation + +Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. + +## Basic Usage + +- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. +- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). +- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. + +## Tailwind CSS v4 Specifics + +- Always use Tailwind CSS v4 and avoid deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. + +### CSS-First Configuration + +In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: + + +@theme { + --color-brand: oklch(0.72 0.11 178); +} + + +### Import Syntax + +In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: + + +- @tailwind base; +- @tailwind components; +- @tailwind utilities; ++ @import "tailwindcss"; + + +### Replaced Utilities + +Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain 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 | + +## Spacing + +Use `gap` utilities instead of margins for spacing between siblings: + + +
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..4b217a09 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,377 @@ + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..4b217a09 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,377 @@ + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/Dockerfile b/Dockerfile index e5772d9b..90743069 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,27 @@ -FROM php:8.2-fpm-alpine AS vendor +FROM code4romania/php:8.4 AS vendor -ENV COMPOSER_ALLOW_SUPERUSER 1 -ENV COMPOSER_HOME /tmp -ENV COMPOSER_CACHE_DIR /dev/null +# Switch to root so we can do root things +USER root -WORKDIR /var/www +# Install additional PHP extensions +RUN set -ex; \ + install-php-extensions \ + sockets -COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +# Drop back to our unprivileged user +USER www-data -RUN apk update && \ - # - # production dependencies - apk add --no-cache \ - nginx && \ - # - # install extensions - install-php-extensions \ - excimer \ - exif \ - gd \ - imagick \ - intl \ - mbstring \ - pdo_mysql \ - zip - -COPY --chown=www-data:www-data . /var/www -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer - -RUN composer install \ +COPY --chown=www-data:www-data . /var/www/html + +RUN set -ex; \ + composer install \ --optimize-autoloader \ --no-interaction \ --no-plugins \ --no-dev \ --prefer-dist -FROM node:22-alpine AS assets +FROM node:24-alpine AS assets WORKDIR /build @@ -46,39 +32,23 @@ COPY \ vite.config.js \ ./ -RUN npm ci --no-audit --ignore-scripts +RUN set -ex; \ + npm ci --no-audit --ignore-scripts -COPY --from=vendor /var/www /build +COPY --from=vendor /var/www/html /build -RUN npm run build +RUN set -ex; \ + npm run build FROM vendor -ARG S6_OVERLAY_VERSION=3.1.6.2 - -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp -RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz /tmp -RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz - -ENTRYPOINT ["/init"] - -COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf -COPY docker/php/php.ini /usr/local/etc/php/php.ini -COPY docker/php/www.conf /usr/local/etc/php-fpm.d/zz-docker.conf -COPY docker/s6-rc.d /etc/s6-overlay/s6-rc.d +ARG VERSION +ARG REVISION -COPY --from=assets --chown=www-data:www-data /build/public/build /var/www/public/build +RUN echo "$VERSION (${REVISION:0:7})" > /var/www/.version -ENV APP_ENV production -ENV APP_DEBUG false -ENV LOG_CHANNEL stderr +COPY --from=assets --chown=www-data:www-data /build/public/build /var/www/html/public/build -# determines what the container should do if one of the service scripts fails -# 0: Continue silently even if a script has failed. -# 1: Continue but warn with an annoying error message.ext script -# 2: Stop the container. -ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 -ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME 0 +ENV WORKER_ENABLED=true -EXPOSE 80 +ENV PHP_PM_MAX_CHILDREN=64 diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 00000000..4b217a09 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,377 @@ + +=== 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 ensure the best experience when 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.16 +- filament/filament (FILAMENT) - v4 +- laravel/framework (LARAVEL) - v12 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/scout (SCOUT) - v10 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/mcp (MCP) - v0 +- laravel/pint (PINT) - v1 +- laravel/sail (SAIL) - v1 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- tailwindcss (TAILWINDCSS) - v4 + +## Skills Activation + +This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. + +- `pest-testing` — Tests applications using the Pest 3 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, architecture testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. +- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. + +## 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, and 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 they work. 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. + +## Documentation Files + +- You must only create documentation files if explicitly requested by the user. + +## Replies + +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +=== 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 trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. +- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax + +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. + +=== php rules === + +# PHP + +- Always use strict typing at the head of a `.php` file: `declare(strict_types=1);`. +- Always use curly braces for control structures, even for single-line bodies. + +## Constructors + +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. + +## Type Declarations + +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Enums + +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + +## Comments + +- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. + +## PHPDoc Blocks + +- Add useful array shape type definitions when appropriate. + +=== 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 --compact` with a specific filename or filter. + +=== 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 `php 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. + +## 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. + +## Queues + +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +## 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 + +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. + +## Laravel 10 Structure + +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +## 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 12 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. + +=== 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. + +=== pest/core rules === + +## Pest + +- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. +- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. +- Do NOT delete tests without approval. +- CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. +- IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. + +=== tailwindcss/core rules === + +# Tailwind CSS + +- Always use existing Tailwind conventions; check project patterns before adding new ones. +- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. +- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. + +=== filament/filament rules === + +## Filament + +- Filament is used by this application. Follow existing conventions for how and where it's implemented. +- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS. +- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices. + +### Artisan + +- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`. +- Inspect required options and always pass `--no-interaction`. + +### Patterns + +Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values. + +Use `Get $get` to read other form field values for conditional logic: + + +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; +use Filament\Schemas\Components\Utilities\Get; + +Select::make('type') + ->options(CompanyType::class) + ->required() + ->live(), + +TextInput::make('company_name') + ->required() + ->visible(fn (Get $get): bool => $get('type') === 'business'), + + +Use `state()` with a `Closure` to compute derived column values: + + +use Filament\Tables\Columns\TextColumn; + +TextColumn::make('full_name') + ->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"), + + +Actions encapsulate a button with optional modal form and logic: + + +use Filament\Actions\Action; +use Filament\Forms\Components\TextInput; + +Action::make('updateEmail') + ->form([ + TextInput::make('email')->email()->required(), + ]) + ->action(fn (array $data, User $record): void => $record->update($data)), + + +### Testing + +Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`: + + + livewire(ListUsers::class) + ->assertCanSeeTableRecords($users) + ->searchTable($users->first()->name) + ->assertCanSeeTableRecords($users->take(1)) + ->assertCanNotSeeTableRecords($users->skip(1)); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => 'Test', + 'email' => 'test@example.com', + ]) + ->call('create') + ->assertNotified() + ->assertRedirect(); + + assertDatabaseHas(User::class, [ + 'name' => 'Test', + 'email' => 'test@example.com', + ]); + + + + livewire(CreateUser::class) + ->fillForm([ + 'name' => null, + 'email' => 'invalid-email', + ]) + ->call('create') + ->assertHasFormErrors([ + 'name' => 'required', + 'email' => 'email', + ]) + ->assertNotNotified(); + + + + use Filament\Actions\DeleteAction; + use Filament\Actions\Testing\TestAction; + + livewire(EditUser::class, ['record' => $user->id]) + ->callAction(DeleteAction::class) + ->assertNotified() + ->assertRedirect(); + + livewire(ListUsers::class) + ->callAction(TestAction::make('promote')->table($user), [ + 'role' => 'admin', + ]) + ->assertNotified(); + + +### Common Mistakes + +**Commonly Incorrect Namespaces:** +- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\` +- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Infolists\Components\` +- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\` +- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\` +- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.) +- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`) + +**Recent breaking changes to Filament:** +- File visibility is `private` by default. Use `->visibility('public')` for public access. +- `Grid`, `Section`, and `Fieldset` no longer span all columns by default. + diff --git a/app/Actions/ExportReport.php b/app/Actions/ExportReport.php index 827edfba..cdf216fe 100644 --- a/app/Actions/ExportReport.php +++ b/app/Actions/ExportReport.php @@ -11,7 +11,7 @@ use Maatwebsite\Excel\Facades\Excel; use Symfony\Component\HttpFoundation\BinaryFileResponse; -class ExportReport extends Action +class ExportReport extends \Filament\Actions\Action { protected ReportType | null $reportType = null; diff --git a/app/Concerns/HasParentResource.php b/app/Concerns/HasParentResource.php index 2d03f25b..3576c5b9 100644 --- a/app/Concerns/HasParentResource.php +++ b/app/Concerns/HasParentResource.php @@ -59,10 +59,10 @@ public static function getParent(): Model|int|string|null return null; } - protected function applyFiltersToTableQuery(Builder $query): Builder + protected function applyFiltersToTableQuery(Builder $query, bool $isResolvingRecord = false): Builder { // Apply any filters before the parent relationship key is applied. - $query = parent::applyFiltersToTableQuery($query); + $query = parent::applyFiltersToTableQuery($query, $isResolvingRecord); return $query->where($this->getParentRelationshipKey(), $this->parent->getKey()); } diff --git a/app/Concerns/PreventSubmitFormOnEnter.php b/app/Concerns/PreventSubmitFormOnEnter.php index 02f04cc2..03b3dbc7 100644 --- a/app/Concerns/PreventSubmitFormOnEnter.php +++ b/app/Concerns/PreventSubmitFormOnEnter.php @@ -10,11 +10,11 @@ trait PreventSubmitFormOnEnter { protected function getCreateFormAction(): Action { - return parent::getCreateFormAction()->extraAttributes(['type' => 'button', 'wire:click' => 'create']); + return parent::getCreateFormAction(); } protected function getSaveFormAction(): Action { - return parent::getSaveFormAction()->extraAttributes(['type' => 'button', 'wire:click' => 'save']); + return parent::getSaveFormAction(); } } diff --git a/app/Concerns/RepeaterDefaultItems.php b/app/Concerns/RepeaterDefaultItems.php index 0317ef89..c54a5a17 100644 --- a/app/Concerns/RepeaterDefaultItems.php +++ b/app/Concerns/RepeaterDefaultItems.php @@ -4,7 +4,7 @@ namespace App\Concerns; -use Filament\Forms\Components\Actions\Action; +use Filament\Actions\Action; trait RepeaterDefaultItems { @@ -20,7 +20,7 @@ protected function setUp(): void return collect($state)->count() > $this->getMinItems(); }); - $this->deleteAction(fn (Action $action) => $action->requiresConfirmation()); + $this->deleteAction(fn (\Filament\Actions\Action $action) => $action->requiresConfirmation()); } public function fillFromRelationship(): void diff --git a/app/Enums/ActLocation.php b/app/Enums/ActLocation.php index 294fd4c4..950460e7 100644 --- a/app/Enums/ActLocation.php +++ b/app/Enums/ActLocation.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum ActLocation: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case DOMICILE = 'domicile'; diff --git a/app/Enums/ActivityDescription.php b/app/Enums/ActivityDescription.php index 79f0a11e..71efa00d 100644 --- a/app/Enums/ActivityDescription.php +++ b/app/Enums/ActivityDescription.php @@ -4,6 +4,7 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; use App\Concerns\Enums; use App\Concerns\Enums\Comparable; use Filament\Support\Contracts\HasLabel; @@ -11,7 +12,7 @@ enum ActivityDescription: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; + use Arrayable; use Comparable; case CREATED = 'created'; diff --git a/app/Enums/AddressType.php b/app/Enums/AddressType.php index 94d4a61e..60cdd187 100644 --- a/app/Enums/AddressType.php +++ b/app/Enums/AddressType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Comparable; +use App\Concerns\Enums\Arrayable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AddressType: string implements HasLabel { use Enums\HasLabel; - use Enums\Comparable; - use Enums\Arrayable; + use Comparable; + use Arrayable; case EFFECTIVE_RESIDENCE = 'effective_residence'; case LEGAL_RESIDENCE = 'legal_residence'; diff --git a/app/Enums/AdminPermission.php b/app/Enums/AdminPermission.php index 69bdb308..1ddb790b 100644 --- a/app/Enums/AdminPermission.php +++ b/app/Enums/AdminPermission.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AdminPermission: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case CAN_CHANGE_NOMENCLATURE = 'can_change_nomenclature'; diff --git a/app/Enums/AdmittanceReason.php b/app/Enums/AdmittanceReason.php index 55886d44..b4621e3f 100644 --- a/app/Enums/AdmittanceReason.php +++ b/app/Enums/AdmittanceReason.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AdmittanceReason: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case SECURITY = 'security'; case EVICTION_FROM_HOME = 'eviction_from_home'; diff --git a/app/Enums/AgeInterval.php b/app/Enums/AgeInterval.php index d7753b3f..95620eb6 100644 --- a/app/Enums/AgeInterval.php +++ b/app/Enums/AgeInterval.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AgeInterval: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case UNDER_1_YEAR = 'under_1_year'; case BETWEEN_1_AND_2_YEARS = 'between_1_and_2_years'; diff --git a/app/Enums/AgeIntervalWithoutChildren.php b/app/Enums/AgeIntervalWithoutChildren.php index a07568d9..731169f0 100644 --- a/app/Enums/AgeIntervalWithoutChildren.php +++ b/app/Enums/AgeIntervalWithoutChildren.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AgeIntervalWithoutChildren: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case BETWEEN_14_AND_17_YEARS = 'between_14_and_17_years'; case BETWEEN_18_AND_25_YEARS = 'between_18_and_25_years'; diff --git a/app/Enums/AggressorLegalHistory.php b/app/Enums/AggressorLegalHistory.php index 12b7db4e..0dc58368 100644 --- a/app/Enums/AggressorLegalHistory.php +++ b/app/Enums/AggressorLegalHistory.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum AggressorLegalHistory: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case CRIMES = 'crimes'; diff --git a/app/Enums/AggressorRelationship.php b/app/Enums/AggressorRelationship.php index 3797be4d..bd892f57 100644 --- a/app/Enums/AggressorRelationship.php +++ b/app/Enums/AggressorRelationship.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum AggressorRelationship: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case MARITAL = 'marital'; diff --git a/app/Enums/AllowancePerson.php b/app/Enums/AllowancePerson.php index 26b03e62..d2a2f2cd 100644 --- a/app/Enums/AllowancePerson.php +++ b/app/Enums/AllowancePerson.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AllowancePerson: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case BENEFICIARY = 'beneficiary'; case OTHER = 'other'; diff --git a/app/Enums/Applicant.php b/app/Enums/Applicant.php index 3a537daa..565ff91a 100644 --- a/app/Enums/Applicant.php +++ b/app/Enums/Applicant.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Applicant: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case BENEFICIARY = 'beneficiary'; diff --git a/app/Enums/AreaType.php b/app/Enums/AreaType.php index 59056105..10a2722d 100644 --- a/app/Enums/AreaType.php +++ b/app/Enums/AreaType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AreaType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case INTERNATIONAL = 'international'; case NATIONAL = 'national'; diff --git a/app/Enums/AwardMethod.php b/app/Enums/AwardMethod.php index 14b01335..cbd8f9e9 100644 --- a/app/Enums/AwardMethod.php +++ b/app/Enums/AwardMethod.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum AwardMethod: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case POSTAL_MONEY_ORDER_AT_HOME = 'postal_money_order_at_home'; case BANK_ACCOUNT = 'bank_account'; diff --git a/app/Enums/BeneficiarySegmentationByAge.php b/app/Enums/BeneficiarySegmentationByAge.php index 8022c26a..8289892a 100644 --- a/app/Enums/BeneficiarySegmentationByAge.php +++ b/app/Enums/BeneficiarySegmentationByAge.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum BeneficiarySegmentationByAge: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case MINOR = 'minor'; case MAJOR = 'major'; diff --git a/app/Enums/CasePermission.php b/app/Enums/CasePermission.php index dbe7c723..c5321776 100644 --- a/app/Enums/CasePermission.php +++ b/app/Enums/CasePermission.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum CasePermission: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case HAS_ACCESS_TO_ALL_CASES = 'has_access_to_all_cases'; diff --git a/app/Enums/CaseStatus.php b/app/Enums/CaseStatus.php index 8b5ba5fa..e139b26d 100644 --- a/app/Enums/CaseStatus.php +++ b/app/Enums/CaseStatus.php @@ -4,6 +4,8 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Colors\Color; use Filament\Support\Contracts\HasColor; @@ -11,8 +13,8 @@ enum CaseStatus: string implements HasLabel, HasColor { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case ACTIVE = 'active'; diff --git a/app/Enums/ChildAggressorRelationship.php b/app/Enums/ChildAggressorRelationship.php index 1f4c0996..0fa7888e 100644 --- a/app/Enums/ChildAggressorRelationship.php +++ b/app/Enums/ChildAggressorRelationship.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum ChildAggressorRelationship: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case CHILD = 'child'; diff --git a/app/Enums/Citizenship.php b/app/Enums/Citizenship.php index 8cb68435..dd6e2a60 100644 --- a/app/Enums/Citizenship.php +++ b/app/Enums/Citizenship.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Citizenship: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case ROMANIAN = 'romanian'; diff --git a/app/Enums/CivilStatus.php b/app/Enums/CivilStatus.php index 09e96398..745053a3 100644 --- a/app/Enums/CivilStatus.php +++ b/app/Enums/CivilStatus.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum CivilStatus: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case SINGLE = 'single'; diff --git a/app/Enums/CloseMethod.php b/app/Enums/CloseMethod.php index f6785772..922ee548 100644 --- a/app/Enums/CloseMethod.php +++ b/app/Enums/CloseMethod.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum CloseMethod: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case ACCORDING_TO_INTERVENTIONAL_PROGRAM = 'according_to_interventional_program'; case TRANSFER_TO = 'transfer_to'; diff --git a/app/Enums/CounselingSheet.php b/app/Enums/CounselingSheet.php index af42d351..80f04975 100644 --- a/app/Enums/CounselingSheet.php +++ b/app/Enums/CounselingSheet.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum CounselingSheet: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case PSYCHOLOGICAL_ASSISTANCE = 'psychological_assistance'; case LEGAL_ASSISTANCE = 'legal_assistance'; diff --git a/app/Enums/DashboardIntervalFilter.php b/app/Enums/DashboardIntervalFilter.php index 84e24c55..83f52a5b 100644 --- a/app/Enums/DashboardIntervalFilter.php +++ b/app/Enums/DashboardIntervalFilter.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Comparable; +use App\Concerns\Enums\Arrayable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum DashboardIntervalFilter: string implements HasLabel { use Enums\HasLabel; - use Enums\Comparable; - use Enums\Arrayable; + use Comparable; + use Arrayable; case TODAY = 'today'; case TOMORROW = 'tomorrow'; diff --git a/app/Enums/DisabilityDegree.php b/app/Enums/DisabilityDegree.php index bb25ac43..b004fb6e 100644 --- a/app/Enums/DisabilityDegree.php +++ b/app/Enums/DisabilityDegree.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum DisabilityDegree: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case EASY = 'easy'; case ENVIRONMENT = 'environment'; diff --git a/app/Enums/DisabilityType.php b/app/Enums/DisabilityType.php index 9b829c38..cf0aa6cc 100644 --- a/app/Enums/DisabilityType.php +++ b/app/Enums/DisabilityType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum DisabilityType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case PHYSICAL = 'physical'; case VISUAL = 'visual'; diff --git a/app/Enums/Diseases.php b/app/Enums/Diseases.php index bc65ae54..0b0253f1 100644 --- a/app/Enums/Diseases.php +++ b/app/Enums/Diseases.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Diseases: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case DENIES_DISEASES = 'denies_diseases'; case CHRONIC_DISEASES = 'chronic_diseases'; diff --git a/app/Enums/Drug.php b/app/Enums/Drug.php index 08e85626..8de26be4 100644 --- a/app/Enums/Drug.php +++ b/app/Enums/Drug.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Drug: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case ALCOHOL_OCCASIONAL = 'alcohol_occasional'; diff --git a/app/Enums/ExtendedFrequency.php b/app/Enums/ExtendedFrequency.php index 0ffff6e4..73ab7d38 100644 --- a/app/Enums/ExtendedFrequency.php +++ b/app/Enums/ExtendedFrequency.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum ExtendedFrequency: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case DAILY = 'daily'; diff --git a/app/Enums/FamilyRelationship.php b/app/Enums/FamilyRelationship.php index ad284b89..03e294b9 100644 --- a/app/Enums/FamilyRelationship.php +++ b/app/Enums/FamilyRelationship.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum FamilyRelationship: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case PARTNER = 'partner'; case MOTHER = 'mother'; diff --git a/app/Enums/FileDocumentType.php b/app/Enums/FileDocumentType.php index 5ddad1a9..d3d698cc 100644 --- a/app/Enums/FileDocumentType.php +++ b/app/Enums/FileDocumentType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum FileDocumentType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case MARRIAGE_CERTIFICATE = 'marriage_certificate'; case CHILDREN_BIRTH_CERTIFICATE = 'children_birth_certificate'; diff --git a/app/Enums/Frequency.php b/app/Enums/Frequency.php index bb338cef..ef38bd82 100644 --- a/app/Enums/Frequency.php +++ b/app/Enums/Frequency.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Frequency: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case DAILY = 'daily'; diff --git a/app/Enums/Gender.php b/app/Enums/Gender.php index 65efecb6..ef9d97e1 100644 --- a/app/Enums/Gender.php +++ b/app/Enums/Gender.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Gender: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case FEMALE = 'female'; diff --git a/app/Enums/GenderShortValues.php b/app/Enums/GenderShortValues.php index b629b17c..5be4f747 100644 --- a/app/Enums/GenderShortValues.php +++ b/app/Enums/GenderShortValues.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum GenderShortValues: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case F = 'f'; diff --git a/app/Enums/Helps.php b/app/Enums/Helps.php index dc9375ed..48e84793 100644 --- a/app/Enums/Helps.php +++ b/app/Enums/Helps.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Helps: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case TEMPORARY_SHELTER = 'temporary_shelter'; diff --git a/app/Enums/HomeOwnership.php b/app/Enums/HomeOwnership.php index ed7b8315..db6a051b 100644 --- a/app/Enums/HomeOwnership.php +++ b/app/Enums/HomeOwnership.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum HomeOwnership: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case NONE = 'none'; diff --git a/app/Enums/HomeType.php b/app/Enums/HomeType.php index 7945aab2..d64fe126 100644 --- a/app/Enums/HomeType.php +++ b/app/Enums/HomeType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum HomeType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case INDIVIDUAL_HOUSE = 'individual_house'; case BUILDING_WITH_MULTIPLE_HOUSES = 'building_with_multiple_houses'; diff --git a/app/Enums/IDType.php b/app/Enums/IDType.php index e91e29fe..82c8ebd7 100644 --- a/app/Enums/IDType.php +++ b/app/Enums/IDType.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum IDType: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case BIRTH_CERTIFICATE = 'birth_certificate'; diff --git a/app/Enums/Income.php b/app/Enums/Income.php index 1984b46e..e56a6d8d 100644 --- a/app/Enums/Income.php +++ b/app/Enums/Income.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Income: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case NONE = 'none'; diff --git a/app/Enums/IncomeSource.php b/app/Enums/IncomeSource.php index fa2dcded..dcae269c 100644 --- a/app/Enums/IncomeSource.php +++ b/app/Enums/IncomeSource.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum IncomeSource: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case SALARY = 'salary'; case PENSION = 'pension'; diff --git a/app/Enums/Level.php b/app/Enums/Level.php index 6258d941..f1539046 100644 --- a/app/Enums/Level.php +++ b/app/Enums/Level.php @@ -4,6 +4,8 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Colors\Color; use Filament\Support\Contracts\HasColor; @@ -12,8 +14,8 @@ enum Level: string implements HasLabel, HasColor, HasIcon { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case HIGH = 'high'; diff --git a/app/Enums/MaintenanceSources.php b/app/Enums/MaintenanceSources.php index 542214ba..77d33923 100644 --- a/app/Enums/MaintenanceSources.php +++ b/app/Enums/MaintenanceSources.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum MaintenanceSources: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case RELATIONSHIP_INCOME = 'relationship_income'; case ALIMONY = 'alimony'; diff --git a/app/Enums/MeetingStatus.php b/app/Enums/MeetingStatus.php index 85644613..b2801526 100644 --- a/app/Enums/MeetingStatus.php +++ b/app/Enums/MeetingStatus.php @@ -4,6 +4,8 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasLabel; @@ -11,8 +13,8 @@ enum MeetingStatus: string implements HasLabel, HasColor { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case PLANED = 'planed'; case REALIZED = 'realized'; diff --git a/app/Enums/NotificationMode.php b/app/Enums/NotificationMode.php index 6f4b3c56..4f4b846f 100644 --- a/app/Enums/NotificationMode.php +++ b/app/Enums/NotificationMode.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum NotificationMode: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case PHONE = 'phone'; diff --git a/app/Enums/Notifier.php b/app/Enums/Notifier.php index a688590d..574f22f3 100644 --- a/app/Enums/Notifier.php +++ b/app/Enums/Notifier.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Notifier: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case VICTIM = 'victim'; diff --git a/app/Enums/Occupation.php b/app/Enums/Occupation.php index 51979da9..edf9d871 100644 --- a/app/Enums/Occupation.php +++ b/app/Enums/Occupation.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Occupation: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case NONE = 'none'; diff --git a/app/Enums/OrganizationType.php b/app/Enums/OrganizationType.php index 9d5aac3d..cc4e6d28 100644 --- a/app/Enums/OrganizationType.php +++ b/app/Enums/OrganizationType.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum OrganizationType: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case NGO = 'ngo'; diff --git a/app/Enums/Patrimony.php b/app/Enums/Patrimony.php index 4f3c41a4..3aa60ab8 100644 --- a/app/Enums/Patrimony.php +++ b/app/Enums/Patrimony.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum Patrimony: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case APARTMENT = 'apartment'; case HOUSE = 'house'; diff --git a/app/Enums/PaymentMethod.php b/app/Enums/PaymentMethod.php index bf13bde4..e09732b9 100644 --- a/app/Enums/PaymentMethod.php +++ b/app/Enums/PaymentMethod.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum PaymentMethod: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case POSTAL_OFFICE = 'postal_office'; case BANK_ACCOUNT = 'bank_account'; case OTHER = 'other'; diff --git a/app/Enums/PossessionMode.php b/app/Enums/PossessionMode.php index 0108cf48..20e61379 100644 --- a/app/Enums/PossessionMode.php +++ b/app/Enums/PossessionMode.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum PossessionMode: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case EXCLUSIVE_PROPERTY = 'exclusive_property'; //case DEVALMASIE = 'devalmasie'; diff --git a/app/Enums/PresentationMode.php b/app/Enums/PresentationMode.php index 60fd2c99..fcc15f2b 100644 --- a/app/Enums/PresentationMode.php +++ b/app/Enums/PresentationMode.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum PresentationMode: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case SPONTANEOUS = 'spontaneous'; diff --git a/app/Enums/ProtectionMeasuringType.php b/app/Enums/ProtectionMeasuringType.php index 94662f44..40e0604f 100644 --- a/app/Enums/ProtectionMeasuringType.php +++ b/app/Enums/ProtectionMeasuringType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum ProtectionMeasuringType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case EMERGENCY_PLACEMENT = 'emergency_placement'; case PLACEMENT_IN_FAMILY = 'placement_in_family'; diff --git a/app/Enums/ProtectionOrder.php b/app/Enums/ProtectionOrder.php index 406e1766..54f0ed84 100644 --- a/app/Enums/ProtectionOrder.php +++ b/app/Enums/ProtectionOrder.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum ProtectionOrder: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case TEMPORARY = 'temporary'; case ISSUED_BY_COURT = 'issued_by_court'; diff --git a/app/Enums/RecommendationService.php b/app/Enums/RecommendationService.php index b9e39b8a..86c6bde1 100644 --- a/app/Enums/RecommendationService.php +++ b/app/Enums/RecommendationService.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum RecommendationService: string implements HasLabel { - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; use Enums\HasLabel; case PSYCHOLOGICAL_ADVICE = 'psychological_advice'; diff --git a/app/Enums/ReferralMode.php b/app/Enums/ReferralMode.php index 1c923cb3..daf5c904 100644 --- a/app/Enums/ReferralMode.php +++ b/app/Enums/ReferralMode.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum ReferralMode: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case VERBAL = 'verbal'; diff --git a/app/Enums/ReportType.php b/app/Enums/ReportType.php index 60deef69..4d0750ae 100644 --- a/app/Enums/ReportType.php +++ b/app/Enums/ReportType.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum ReportType: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case CASES_BY_AGE = 'cases_by_age'; case CASES_BY_AGE_SEGMENTATION = 'cases_by_age_segmentation'; diff --git a/app/Enums/ResidenceEnvironment.php b/app/Enums/ResidenceEnvironment.php index e56e2f11..fef50318 100644 --- a/app/Enums/ResidenceEnvironment.php +++ b/app/Enums/ResidenceEnvironment.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum ResidenceEnvironment: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case URBAN = 'urban'; diff --git a/app/Enums/SocialRelationship.php b/app/Enums/SocialRelationship.php index 4b37d442..100f94da 100644 --- a/app/Enums/SocialRelationship.php +++ b/app/Enums/SocialRelationship.php @@ -4,14 +4,16 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns\Enums; use Filament\Support\Contracts\HasLabel; enum SocialRelationship: string implements HasLabel { use Enums\HasLabel; - use Enums\Arrayable; - use Enums\Comparable; + use Arrayable; + use Comparable; case FRIEND = 'friend'; case COWORKER = 'coworker'; diff --git a/app/Enums/Studies.php b/app/Enums/Studies.php index ce1568f4..034309d1 100644 --- a/app/Enums/Studies.php +++ b/app/Enums/Studies.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Studies: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case NONE = 'none'; diff --git a/app/Enums/Ternary.php b/app/Enums/Ternary.php index a3c81327..5e15055e 100644 --- a/app/Enums/Ternary.php +++ b/app/Enums/Ternary.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Ternary: int implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case YES = 1; diff --git a/app/Enums/Violence.php b/app/Enums/Violence.php index e80af409..caa59b7c 100644 --- a/app/Enums/Violence.php +++ b/app/Enums/Violence.php @@ -4,13 +4,15 @@ namespace App\Enums; +use App\Concerns\Enums\Arrayable; +use App\Concerns\Enums\Comparable; use App\Concerns; use Filament\Support\Contracts\HasLabel; enum Violence: string implements HasLabel { - use Concerns\Enums\Arrayable; - use Concerns\Enums\Comparable; + use Arrayable; + use Comparable; use Concerns\Enums\HasLabel; case VERBAL = 'verbal'; diff --git a/app/Filament/Admin/Actions/ChangeNomenclatureStatusAction.php b/app/Filament/Admin/Actions/ChangeNomenclatureStatusAction.php index e1dfb11b..5b813e0a 100644 --- a/app/Filament/Admin/Actions/ChangeNomenclatureStatusAction.php +++ b/app/Filament/Admin/Actions/ChangeNomenclatureStatusAction.php @@ -35,14 +35,14 @@ protected function setUp(): void $record->$relationship()->update(['status' => GeneralStatus::INACTIVE]); } }); - - $recordClass = \get_class($this->getRecord()); - $recordClass = strtolower(substr($recordClass, strrpos($recordClass, '\\') + 1)); - $modalLabelKey = \sprintf('inactivate_%s_modal', $recordClass); - - $this->modalHeading(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.headings.' . $modalLabelKey) : null); - $this->modalDescription(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.helper_texts.' . $modalLabelKey) : null); - $this->modalSubmitActionLabel(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.actions.change_status.' . $modalLabelKey) : null); +// +// $recordClass = \get_class($this->getRecord()); +// $recordClass = strtolower(substr($recordClass, strrpos($recordClass, '\\') + 1)); +// $modalLabelKey = \sprintf('inactivate_%s_modal', $recordClass); +// +// $this->modalHeading(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.headings.' . $modalLabelKey) : null); +// $this->modalDescription(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.helper_texts.' . $modalLabelKey) : null); +// $this->modalSubmitActionLabel(fn ($record) => GeneralStatus::isValue($record->status, GeneralStatus::ACTIVE) ? __('nomenclature.actions.change_status.' . $modalLabelKey) : null); $this->modalFooterActionsAlignment(Alignment::Right); } diff --git a/app/Filament/Admin/Pages/Auth/Login.php b/app/Filament/Admin/Pages/Auth/Login.php index d299ea09..91cb7ae3 100644 --- a/app/Filament/Admin/Pages/Auth/Login.php +++ b/app/Filament/Admin/Pages/Auth/Login.php @@ -6,7 +6,7 @@ use Filament\Pages\Auth\Login as BaseLogin; -class Login extends BaseLogin +class Login extends \Filament\Auth\Pages\Login { public function mount(): void { diff --git a/app/Filament/Admin/Resources/BenefitResource.php b/app/Filament/Admin/Resources/BenefitResource.php index 64c6aecd..aac98e30 100644 --- a/app/Filament/Admin/Resources/BenefitResource.php +++ b/app/Filament/Admin/Resources/BenefitResource.php @@ -4,22 +4,14 @@ namespace App\Filament\Admin\Resources; -use App\Enums\GeneralStatus; -use App\Filament\Admin\Resources\BenefitResource\Pages; -use App\Forms\Components\TableRepeater; +use App\Filament\Admin\Schemas\BenefitResourceSchema; +use App\Filament\Admin\Resources\BenefitResource\Pages\ListBenefits; +use App\Filament\Admin\Resources\BenefitResource\Pages\CreateBenefit; +use App\Filament\Admin\Resources\BenefitResource\Pages\ViewBenefit; +use App\Filament\Admin\Resources\BenefitResource\Pages\EditBenefit; use App\Models\Benefit; -use App\Models\BenefitService; -use Awcodes\TableRepeater\Header; -use Filament\Forms\Components\Actions\Action; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables\Actions\CreateAction; -use Filament\Tables\Actions\ViewAction; -use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; class BenefitResource extends Resource @@ -28,114 +20,23 @@ class BenefitResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - Section::make() - ->schema([ - TextInput::make('name') - ->label(__('nomenclature.labels.benefit_name')) - ->maxWidth('3xl') - ->maxLength(200) - ->required(), - - TableRepeater::make('benefitTypes') - ->relationship('benefitTypes') - ->label(__('nomenclature.headings.benefit_types')) - ->helperText(__('nomenclature.helper_texts.benefit_types')) - ->reorderable() - ->orderColumn() - ->columnSpanFull() - ->minItems(1) - ->showLabels() - ->addActionLabel(__('nomenclature.actions.add_benefit_type')) - ->headers([ - Header::make('name') - ->label(__('nomenclature.labels.benefit_type_name')) - ->markAsRequired(), - - Header::make('status') - ->label(__('nomenclature.labels.status')), - ]) - ->schema([ - TextInput::make('name') - ->label(__('nomenclature.labels.benefit_type_name')) - ->hiddenLabel() - ->maxLength(200) - ->required(), - - Toggle::make('status') - ->live() - ->default(true) - ->label( - fn (bool $state) => $state - ? __('nomenclature.labels.active') - : __('nomenclature.labels.inactive') - ), - ]) - ->deleteAction( - fn (Action $action) => $action - ->disabled(function (array $arguments, TableRepeater $component): bool { - $items = $component->getState(); - $currentItem = $items[$arguments['item']]; - - if (! isset($currentItem['id'])) { - return false; - } - - return (bool) BenefitService::query() - ->whereJsonContains('benefit_types', \sprintf('%s', $currentItem['id'])) - ->count(); - }) - ), - ]), - ]); + return BenefitResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->headerActions([ - CreateAction::make() - ->label(__('nomenclature.actions.add_benefit')) - ->url(self::getUrl('create')), - ]) - ->heading(__('nomenclature.headings.benefit_table')) - ->columns([ - TextColumn::make('name') - ->label(__('nomenclature.labels.benefit')), - - TextColumn::make('institutions_count') - ->label(__('nomenclature.labels.institutions')), - - TextColumn::make('organizations_count') - ->label(__('nomenclature.labels.centers')), - - TextColumn::make('status') - ->label(__('nomenclature.labels.status')), - ]) - ->actions([ - ViewAction::make() - ->label(__('general.action.view_details')) - ->url(fn (Benefit $record) => BenefitResource::getUrl('view', ['record' => $record])), - ]) - ->filters([ - SelectFilter::make('status') - ->options(GeneralStatus::options()), - ]) - ->emptyStateHeading(__('nomenclature.headings.empty_state_benefit_table')) - ->emptyStateDescription(null) - ->emptyStateIcon('heroicon-o-clipboard-document-check'); + return BenefitResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListBenefits::route('/'), - 'create' => Pages\CreateBenefit::route('/create'), - 'view' => Pages\ViewBenefit::route('/{record}'), - 'edit' => Pages\EditBenefit::route('/{record}/edit'), + 'index' => ListBenefits::route('/'), + 'create' => CreateBenefit::route('/create'), + 'view' => ViewBenefit::route('/{record}'), + 'edit' => EditBenefit::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Admin/Resources/BenefitResource/Pages/EditBenefit.php b/app/Filament/Admin/Resources/BenefitResource/Pages/EditBenefit.php index cc0cd3d9..dcb047c2 100644 --- a/app/Filament/Admin/Resources/BenefitResource/Pages/EditBenefit.php +++ b/app/Filament/Admin/Resources/BenefitResource/Pages/EditBenefit.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\BenefitResource\Pages; +use Filament\Actions\DeleteAction; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Actions\ChangeNomenclatureStatusAction; @@ -44,14 +45,14 @@ protected function getHeaderActions(): array ChangeNomenclatureStatusAction::make(), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('nomenclature.actions.delete_benefit')) ->icon('heroicon-s-trash') ->outlined() ->disabled(fn () => $this->getRecord()->benefitServices()->count()) ->successRedirectUrl(self::$resource::getUrl()) // tooltip doesn't work if action is disabled - ->tooltip(fn (Actions\DeleteAction $action) => $action->isDisabled() ? __('nomenclature.helper_texts.delete_benefit') : ''), + ->tooltip(fn (DeleteAction $action) => $action->isDisabled() ? __('nomenclature.helper_texts.delete_benefit') : ''), ]; } diff --git a/app/Filament/Admin/Resources/BenefitResource/Pages/ListBenefits.php b/app/Filament/Admin/Resources/BenefitResource/Pages/ListBenefits.php index f811c7dc..da99d014 100644 --- a/app/Filament/Admin/Resources/BenefitResource/Pages/ListBenefits.php +++ b/app/Filament/Admin/Resources/BenefitResource/Pages/ListBenefits.php @@ -12,7 +12,7 @@ class ListBenefits extends ManageRecords { protected static string $resource = BenefitResource::class; - protected static string $view = 'filament.admin.pages.nomenclature-list'; + protected string $view = 'filament.admin.pages.nomenclature-list'; public function getTitle(): string|Htmlable { diff --git a/app/Filament/Admin/Resources/BenefitResource/Pages/ViewBenefit.php b/app/Filament/Admin/Resources/BenefitResource/Pages/ViewBenefit.php index 7fe93ff4..60cb9281 100644 --- a/app/Filament/Admin/Resources/BenefitResource/Pages/ViewBenefit.php +++ b/app/Filament/Admin/Resources/BenefitResource/Pages/ViewBenefit.php @@ -4,11 +4,12 @@ namespace App\Filament\Admin\Resources\BenefitResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Filament\Admin\Resources\BenefitResource; use App\Infolists\Components\TableEntry; use Filament\Actions\EditAction; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -18,7 +19,7 @@ class ViewBenefit extends ViewRecord { protected static string $resource = BenefitResource::class; - public function getFooterWidgetsColumns(): int|string|array + public function getFooterWidgetsColumns(): int|array { return 1; } @@ -47,9 +48,9 @@ public function getTitle(): string|Htmlable return $this->record->name; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') ->schema([ diff --git a/app/Filament/Admin/Resources/InstitutionResource.php b/app/Filament/Admin/Resources/InstitutionResource.php index 3d305adf..1f727dab 100644 --- a/app/Filament/Admin/Resources/InstitutionResource.php +++ b/app/Filament/Admin/Resources/InstitutionResource.php @@ -4,22 +4,24 @@ namespace App\Filament\Admin\Resources; -use App\Filament\Admin\Resources\InstitutionResource\Pages; -use App\Filament\Admin\Resources\UserInstitutionResource\Pages\EditUserInstitution; -use App\Filament\Admin\Resources\UserInstitutionResource\Pages\ViewUserInstitution; +use App\Filament\Admin\Schemas\InstitutionResourceSchema; +use App\Filament\Admin\Resources\InstitutionResource\Pages\ListInstitutions; +use App\Filament\Admin\Resources\InstitutionResource\Pages\CreateInstitution; +use App\Filament\Admin\Resources\InstitutionResource\Pages\ViewInstitution; +use App\Filament\Admin\Resources\InstitutionResource\Pages\EditInstitutionDetails; +use App\Filament\Admin\Resources\InstitutionResource\Pages\EditInstitutionCenters; +use App\Filament\Admin\Resources\InstitutionResource\RelationManagers\AdminsRelationManager; +use App\Filament\Admin\Resources\InstitutionResource\RelationManagers\OrganizationsRelationManager; use App\Models\Institution; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables\Actions\ViewAction; -use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; class InstitutionResource extends Resource { protected static ?string $model = Institution::class; - protected static ?string $navigationIcon = 'heroicon-o-users'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-users'; public static function getNavigationSort(): ?int { @@ -41,66 +43,32 @@ public static function getNavigationLabel(): string return __('institution.headings.list_title'); } - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - // - ]); + return InstitutionResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing( - fn (Builder $query) => $query - ->withCount(['organizations', 'beneficiaries', 'users']) - ->with(['county', 'city']) - ) - ->defaultSort('created_at', 'desc') - ->columns([ - TextColumn::make('name') - ->label(__('institution.headings.institution_name')), - - TextColumn::make('county_and_city') - ->label(__('institution.headings.registered_office')), - - TextColumn::make('organizations_count') - ->label(__('institution.headings.centers')), - - TextColumn::make('beneficiaries_count') - ->label(__('institution.headings.cases')), - - TextColumn::make('users_count') - ->label(__('institution.headings.specialists')), + return InstitutionResourceSchema::table($table); + } - TextColumn::make('status') - ->label(__('institution.headings.status')), - ]) - ->filters([ - // - ]) - ->actions([ - ViewAction::make() - ->label(__('general.action.view_details')), - ]) - ->heading(__('institution.headings.all_institutions')) - ->description(trans_choice('institution.headings.count', Institution::count(), ['count' => Institution::count()])) - ->emptyStateIcon('heroicon-o-clipboard-document-list') - ->emptyStateHeading(__('institution.headings.empty_state')) - ->emptyStateDescription(null); + public static function getRelations(): array + { + return [ + 'admins' => AdminsRelationManager::class, + 'organizations' => OrganizationsRelationManager::class, + ]; } public static function getPages(): array { return [ - 'index' => Pages\ListInstitutions::route('/'), - 'create' => Pages\CreateInstitution::route('/create'), - 'view' => Pages\ViewInstitution::route('/{record}'), - 'edit_institution_details' => Pages\EditInstitutionDetails::route('/{record}/editInstitutionDetails'), - 'edit_institution_centers' => Pages\EditInstitutionCenters::route('/{record}/editCenters'), - 'user.view' => ViewUserInstitution::route('{parent}/user/{record}'), - 'user.edit' => EditUserInstitution::route('{parent}/user/{record}/edit'), + 'index' => ListInstitutions::route('/'), + 'create' => CreateInstitution::route('/create'), + 'view' => ViewInstitution::route('/{record}'), + 'edit_institution_details' => EditInstitutionDetails::route('/{record}/editInstitutionDetails'), + 'edit_institution_centers' => EditInstitutionCenters::route('/{record}/editCenters'), ]; } } diff --git a/app/Filament/Admin/Resources/InstitutionResource/Pages/CreateInstitution.php b/app/Filament/Admin/Resources/InstitutionResource/Pages/CreateInstitution.php index e5fc4be0..c2f02cfd 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/Pages/CreateInstitution.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Pages/CreateInstitution.php @@ -7,11 +7,11 @@ use App\Concerns\PreventMultipleSubmit; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Resources\InstitutionResource; -use App\Filament\Admin\Resources\UserInstitutionResource\Pages\EditUserInstitution; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Pages\EditUserInstitution; use App\Forms\Components\Repeater; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Wizard\Step; +use Filament\Schemas\Components\Wizard\Step; use Filament\Resources\Pages\Concerns\HasWizard; use Filament\Resources\Pages\CreateRecord; use Illuminate\Contracts\Support\Htmlable; @@ -38,7 +38,7 @@ public function getSteps(): array { return [ Step::make(__('institution.headings.institution_details')) - ->schema(EditInstitutionDetails::getSchema()), + ->schema(EditInstitutionDetails::getFormComponents()), Step::make(__('institution.headings.center_details')) ->schema([ @@ -47,7 +47,7 @@ public function getSteps(): array ->maxWidth('3xl') ->content(__('institution.placeholders.center_details')), - ...EditInstitutionCenters::getSchema(), + ...\App\Filament\Admin\Schemas\InstitutionResourceSchema::getFormSchemaForCenters(), ]), Step::make(__('institution.headings.ngo_admin')) @@ -65,7 +65,7 @@ public function getSteps(): array ->relationship('admins') ->addActionLabel(__('institution.actions.add_admin')) ->schema([ - ...EditUserInstitution::getSchema(), + ...EditUserInstitution::getFormComponents(), Hidden::make('ngo_admin') ->default(1), diff --git a/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionCenters.php b/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionCenters.php index 7044e30b..4df3c5ae 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionCenters.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionCenters.php @@ -4,14 +4,12 @@ namespace App\Filament\Admin\Resources\InstitutionResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Resources\InstitutionResource; -use App\Forms\Components\Repeater; +use App\Filament\Admin\Schemas\InstitutionResourceSchema; use App\Models\Organization; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; @@ -50,89 +48,21 @@ public function getHeaderActions(): array ]; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); - } - - public static function getSchema(): array - { - return [ - Repeater::make('organizations') - ->maxWidth('3xl') - ->hiddenLabel() - ->columns() - ->minItems(1) - ->relationship('organizations') - ->addActionLabel(__('institution.actions.add_organization')) - ->schema([ - TextInput::make('name') - ->label(__('institution.labels.center_name')) - ->placeholder(__('organization.placeholders.center_name')) - ->maxLength(200) - ->required(), - - TextInput::make('short_name') - ->label(__('organization.field.short_name')) - ->placeholder(__('organization.placeholders.center_short_name')) - ->maxLength(50), - - TextInput::make('main_activity') - ->label(__('organization.field.main_activity')) - ->placeholder(__('organization.placeholders.main_activity')) - ->columnSpanFull() - ->maxLength(200) - ->required(), - - SpatieMediaLibraryFileUpload::make('social_service_licensing_certificate') - ->label(__('institution.labels.social_service_licensing_certificate')) - ->helperText(__('institution.helper_texts.social_service_licensing_certificate')) - ->maxSize(config('media-library.max_file_size')) - ->collection('social_service_licensing_certificate') - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'application/pdf', - 'image/*', - ]) - ->columnSpanFull(), - - SpatieMediaLibraryFileUpload::make('logo') - ->label(__('institution.labels.logo_center')) - ->helperText(__('institution.helper_texts.logo')) - ->maxSize(config('media-library.max_file_size')) - ->collection('logo') - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'image/*', - ]) - ->columnSpanFull(), - - SpatieMediaLibraryFileUpload::make('organization_header') - ->label(__('institution.labels.organization_header')) - ->helperText(__('institution.helper_texts.organization_header')) - ->maxSize(config('media-library.max_file_size')) - ->collection('organization_header') - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'image/*', - ]) - ->columnSpanFull(), - ]), - ]; + return $schema->components(InstitutionResourceSchema::getFormSchemaForCenters()); } public function afterSave() { $this->getRecord() - ->organizations + ->organizations->load('admins') ?->each( fn (Organization $organization) => $organization ->admins() ->attach( $this->getRecord() + ->load('admins') ->admins ->pluck('id') ->diff( diff --git a/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionDetails.php b/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionDetails.php index 58256ffd..34a3ecb7 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionDetails.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Pages/EditInstitutionDetails.php @@ -4,18 +4,11 @@ namespace App\Filament\Admin\Resources\InstitutionResource\Pages; +use App\Filament\Admin\Schemas\InstitutionResourceSchema; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; -use App\Enums\AreaType; -use App\Enums\OrganizationType; use App\Filament\Admin\Resources\InstitutionResource; -use App\Forms\Components\Location; -use App\Forms\Components\Select; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; @@ -43,9 +36,9 @@ public function getTitle(): string|Htmlable return $this->getRecord()->name; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components(InstitutionResourceSchema::getFormSchemaForDetails()); } public function getHeaderActions(): array @@ -56,135 +49,8 @@ public function getHeaderActions(): array ]; } - public static function getSchema(): array + public static function getFormComponents(): array { - return [ - Section::make() - ->maxWidth('3xl') - ->columns() - ->schema([ - TextInput::make('name') - ->label(__('organization.field.name')) - ->placeholder(__('organization.placeholders.name')) - ->maxLength(200) - ->required(), - - TextInput::make('short_name') - ->label(__('organization.field.short_name')) - ->placeholder(__('organization.placeholders.short_name')) - ->maxLength(50), - - Select::make('type') - ->label(__('organization.field.type')) - ->placeholder(__('organization.placeholders.type')) - ->options(OrganizationType::options()) - ->enum(OrganizationType::class) - ->required(), - - TextInput::make('cif') - ->label(__('organization.field.cif')) - ->placeholder(__('organization.placeholders.cif')) - ->required(), - - TextInput::make('main_activity') - ->label(__('organization.field.main_activity')) - ->placeholder(__('organization.placeholders.main_activity')) - ->maxLength(200) - ->required(), - - Select::make('area') - ->label(__('organization.field.area')) - ->placeholder(__('organization.placeholders.area')) - ->options(AreaType::options()) - ->required(), - - Location::make() - ->city() - ->address() - ->countyLabel(__('organization.field.county')) - ->cityLabel(__('organization.field.city')) - ->addressLabel(__('organization.field.address')) - ->addressMaxLength(200) - ->addressColumnSpanFull() - ->required(), - - Grid::make() - ->schema([ - TextInput::make('representative_person.name') - ->label(__('organization.field.representative_name')) - ->placeholder(__('organization.placeholders.representative_name')) - ->maxLength(50) - ->required(), - - TextInput::make('representative_person.email') - ->label(__('organization.field.representative_email')) - ->placeholder(__('organization.placeholders.representative_email')) - ->maxLength(50) - ->email(), - - TextInput::make('representative_person.phone') - ->label(__('organization.field.representative_phone')) - ->placeholder(__('organization.placeholders.representative_phone')) - ->maxLength(13) - ->tel(), - ])->columnSpanFull(), - - Grid::make() - ->schema([ - TextInput::make('contact_person.name') - ->label(__('organization.field.contact_person')) - ->placeholder(__('organization.placeholders.contact_person')) - ->maxLength(50) - ->required(), - - TextInput::make('contact_person.email') - ->label(__('organization.field.contact_person_email')) - ->placeholder(__('organization.placeholders.contact_person_email')) - ->maxLength(50) - ->required() - ->email(), - - TextInput::make('contact_person.phone') - ->label(__('organization.field.contact_person_phone')) - ->placeholder(__('organization.placeholders.contact_person_phone')) - ->maxLength(13) - ->tel() - ->required(), - ])->columnSpanFull(), - - TextInput::make('website') - ->label(__('organization.field.website')) - ->placeholder(__('organization.placeholders.website')) - ->maxLength(200) - ->url(), - - SpatieMediaLibraryFileUpload::make('organization_status') - ->label(__('institution.labels.organization_status')) - ->maxSize(config('media-library.max_file_size')) - ->helperText(__('institution.helper_texts.organization_status')) - ->collection('organization_status') - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'application/pdf', - 'image/*', - ]) - ->columnSpanFull() - ->required(), - - SpatieMediaLibraryFileUpload::make('social_service_provider_certificate') - ->label(__('institution.labels.social_service_provider_certificate')) - ->maxSize(config('media-library.max_file_size')) - ->helperText(__('institution.helper_texts.social_service_provider_certificate')) - ->collection('social_service_provider_certificate') - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'application/pdf', - 'image/*', - ]) - ->columnSpanFull(), - ]), - ]; + return InstitutionResourceSchema::getFormSchemaForDetails(); } } diff --git a/app/Filament/Admin/Resources/InstitutionResource/Pages/ListInstitutions.php b/app/Filament/Admin/Resources/InstitutionResource/Pages/ListInstitutions.php index 899e7b0b..a9a17448 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/Pages/ListInstitutions.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Pages/ListInstitutions.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\InstitutionResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Admin\Resources\InstitutionResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -26,7 +27,7 @@ public function getBreadcrumbs(): array protected function getHeaderActions(): array { return [ - Actions\CreateAction::make() + CreateAction::make() ->label(__('institution.actions.create')), ]; } diff --git a/app/Filament/Admin/Resources/InstitutionResource/Pages/ViewInstitution.php b/app/Filament/Admin/Resources/InstitutionResource/Pages/ViewInstitution.php index 60b90b4f..92de9102 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/Pages/ViewInstitution.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Pages/ViewInstitution.php @@ -4,6 +4,10 @@ namespace App\Filament\Admin\Resources\InstitutionResource\Pages; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Schema; +use App\Filament\Admin\Resources\InstitutionResource\RelationManagers\OrganizationsRelationManager; +use App\Filament\Admin\Resources\InstitutionResource\RelationManagers\AdminsRelationManager; use App\Actions\BackAction; use App\Filament\Admin\Resources\InstitutionResource; use App\Filament\Admin\Resources\InstitutionResource\Actions\ActivateInstitution; @@ -11,7 +15,6 @@ use App\Infolists\Components\Actions\EditAction; use App\Infolists\Components\DocumentPreview; use App\Infolists\Components\Location; -use Filament\Infolists\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -46,9 +49,9 @@ protected function getActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make(__('institution.headings.institution_details')) ->headerActions([ EditAction::make() @@ -141,11 +144,4 @@ public function getContentTabLabel(): ?string return __('institution.headings.institution_details'); } - public function getRelationManagers(): array - { - return [ - 'organizations' => InstitutionResource\RelationManagers\OrganizationsRelationManager::make(), - 'admins' => InstitutionResource\RelationManagers\AdminsRelationManager::make(), - ]; - } } diff --git a/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/AdminsRelationManager.php b/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/AdminsRelationManager.php index 01d968eb..0af0fdc6 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/AdminsRelationManager.php +++ b/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/AdminsRelationManager.php @@ -4,15 +4,15 @@ namespace App\Filament\Admin\Resources\InstitutionResource\RelationManagers; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Resources\InstitutionResource; -use App\Filament\Admin\Resources\UserInstitutionResource\Pages\EditUserInstitution; +use App\Filament\Admin\Schemas\UserInstitutionResourceSchema; use App\Tables\Columns\DateTimeColumn; -use Filament\Forms\Components\Hidden; -use Filament\Forms\Form; +use Filament\Actions\ViewAction; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables\Actions\CreateAction; -use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; @@ -24,24 +24,22 @@ class AdminsRelationManager extends RelationManager protected static string $relationship = 'admins'; + protected static ?string $relatedResource = UserInstitutionResource::class; + public function isReadOnly(): bool { return false; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema([ - ...EditUserInstitution::getSchema(), - - Hidden::make('ngo_admin') - ->default(1), - ]); + return UserInstitutionResourceSchema::form($schema); } public function table(Table $table): Table { + $ownerRecord = $this->getOwnerRecord(); + return $table ->modifyQueryUsing(fn (Builder $query) => $query->with('roles')) ->heading(__('institution.headings.admin_users')) @@ -62,20 +60,14 @@ public function table(Table $table): Table ->label(__('institution.labels.last_login_at')), ]) ->headerActions([ - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('institution.actions.add_ngo_admin')) ->modalHeading(__('institution.actions.add_ngo_admin')) ->createAnother(false), ]) - ->actions([ + ->recordActions([ ViewAction::make() - ->label(__('general.action.view_details')) - ->url( - fn ($record) => InstitutionResource::getUrl('user.view', [ - 'parent' => $this->getOwnerRecord(), - 'record' => $record, - ]) - ), + ->label(__('general.action.view_details')), ]); } diff --git a/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/OrganizationsRelationManager.php b/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/OrganizationsRelationManager.php index 3f28766d..92fe6139 100644 --- a/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/OrganizationsRelationManager.php +++ b/app/Filament/Admin/Resources/InstitutionResource/RelationManagers/OrganizationsRelationManager.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\InstitutionResource\RelationManagers; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Resources\InstitutionResource; use App\Infolists\Components\Actions\EditAction; @@ -11,7 +12,7 @@ use App\Models\Institution; use Filament\Facades\Filament; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\RelationManagers\RelationManager; @@ -23,16 +24,16 @@ class OrganizationsRelationManager extends RelationManager protected static string $relationship = 'organizations'; - protected static string $view = 'infolists.infolist-relation-manager'; + protected string $view = 'infolists.infolist-relation-manager'; public static function getTitle(Model $ownerRecord, string $pageClass): string { return __('institution.headings.center_details'); } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->heading(__('institution.headings.center_details')) ->headerActions([ diff --git a/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource.php new file mode 100644 index 00000000..507728ea --- /dev/null +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource.php @@ -0,0 +1,39 @@ +relationship('admins') + ->inverseRelationship('institution'); + } + + public static function getPages(): array + { + return [ + 'index' => ListUserInstitutions::route('/'), + 'view' => Pages\ViewUserInstitution::route('/{record}'), + 'edit' => Pages\EditUserInstitution::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/ActivateUserAction.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ActivateUserAction.php similarity index 92% rename from app/Filament/Admin/Resources/UserInstitutionResource/Actions/ActivateUserAction.php rename to app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ActivateUserAction.php index 1f025d6d..f7238ed1 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/ActivateUserAction.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ActivateUserAction.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Filament\Admin\Resources\UserInstitutionResource\Actions; +namespace App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions; use App\Models\Organization; use App\Models\User; diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php similarity index 93% rename from app/Filament/Admin/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php rename to app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php index 7aaa187c..782d1292 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/DeactivateUserAction.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Filament\Admin\Resources\UserInstitutionResource\Actions; +namespace App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions; use App\Models\Organization; use App\Models\User; diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php similarity index 94% rename from app/Filament/Admin/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php rename to app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php index d16b2b24..704b1348 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Actions/ResendInvitationAction.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Filament\Admin\Resources\UserInstitutionResource\Actions; +namespace App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions; use App\Models\Organization; use App\Models\User; diff --git a/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/EditUserInstitution.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/EditUserInstitution.php new file mode 100644 index 00000000..67cf252e --- /dev/null +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/EditUserInstitution.php @@ -0,0 +1,69 @@ +getParentRecord(); + + return InstitutionResource::getUrl('view', [ + 'record' => $parentRecord, + 'activeRelationManager' => 'admins', + ]); + } + + public function getBreadcrumbs(): array + { + $parentRecord = $this->getParentRecord(); + $record = $this->getRecord(); + + return [ + InstitutionResource::getUrl() => __('institution.headings.list_title'), + InstitutionResource::getUrl('view', ['record' => $parentRecord]) => $parentRecord->name, + static::getResource()::getUrl('view', [ + 'institution' => $parentRecord, + 'record' => $record, + ]) => $record->full_name, + ]; + } + + public function getTitle(): string|Htmlable + { + return $this->getRecord()->full_name; + } + + public function getHeaderActions(): array + { + return [ + BackAction::make() + ->url($this->getRedirectUrl()), + ]; + } + + public function form(Schema $schema): Schema + { + return UserInstitutionResourceSchema::form($schema); + } + + public static function getFormComponents(): array + { + return UserInstitutionResourceSchema::getFormComponents(); + } +} diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php similarity index 54% rename from app/Filament/Admin/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php rename to app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php index 67c4c425..10d5a4f4 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ListUserInstitutions.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace App\Filament\Admin\Resources\UserInstitutionResource\Pages; +namespace App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Pages; -use App\Filament\Admin\Resources\UserInstitutionResource; +use Filament\Actions\CreateAction; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListUserInstitutions extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php similarity index 57% rename from app/Filament/Admin/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php rename to app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php index 35411beb..a8b15392 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php +++ b/app/Filament/Admin/Resources/InstitutionResource/Resources/UserInstitutionResource/Pages/ViewUserInstitution.php @@ -2,46 +2,49 @@ declare(strict_types=1); -namespace App\Filament\Admin\Resources\UserInstitutionResource\Pages; +namespace App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; -use App\Concerns\HasParentResource; use App\Filament\Admin\Resources\InstitutionResource; -use App\Filament\Admin\Resources\UserInstitutionResource; -use App\Filament\Admin\Resources\UserInstitutionResource\Actions\ActivateUserAction; -use App\Filament\Admin\Resources\UserInstitutionResource\Actions\DeactivateUserAction; -use App\Filament\Admin\Resources\UserInstitutionResource\Actions\ResendInvitationAction; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions\ActivateUserAction; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions\DeactivateUserAction; +use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource\Actions\ResendInvitationAction; use App\Infolists\Components\Actions\EditAction; use App\Infolists\Components\DateTimeEntry; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; -use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; use Illuminate\Contracts\Support\Htmlable; class ViewUserInstitution extends ViewRecord { - use HasParentResource; - protected static string $resource = UserInstitutionResource::class; + protected static ?string $parentResource = InstitutionResource::class; protected function getRedirectUrl(): ?string { - return self::getParentResource()::getUrl('view', [ - 'record' => $this->parent, + $parentRecord = $this->getParentRecord(); + + return InstitutionResource::getUrl('view', [ + 'record' => $parentRecord, 'activeRelationManager' => 'admins', ]); } public function getBreadcrumbs(): array { + $parentRecord = $this->getParentRecord(); + $record = $this->getRecord(); + return [ InstitutionResource::getUrl() => __('institution.headings.list_title'), - InstitutionResource::getUrl('view', ['record' => $this->parent]) => $this->parent->name, - InstitutionResource::getUrl('user.view', [ - 'parent' => $this->parent, - 'record' => $this->getRecord(), - ]) => $this->getRecord()->full_name, + InstitutionResource::getUrl('view', ['record' => $parentRecord]) => $parentRecord->name, + static::getResource()::getUrl('view', [ + 'institution' => $parentRecord, + 'record' => $record, + ]) => $record->full_name, ]; } @@ -64,9 +67,12 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + $record = $this->getRecord(); + $parentRecord = $this->getParentRecord(); + + return $schema->components([ Section::make() ->maxWidth('3xl') ->columns() @@ -82,10 +88,12 @@ public function infolist(Infolist $infolist): Infolist ->heading(__('user.heading.specialist_details')) ->headerActions([ EditAction::make() - ->url(self::getParentResource()::getUrl('user.edit', [ - 'parent' => $this->parent, - 'record' => $this->getRecord(), - ])), + ->url(function () use ($record, $parentRecord) { + return static::getResource()::getUrl('edit', [ + 'institution' => $parentRecord, + 'record' => $record, + ]); + }), ]) ->maxWidth('3xl') ->columns() diff --git a/app/Filament/Admin/Resources/ResultResource.php b/app/Filament/Admin/Resources/ResultResource.php index a501dce3..36b80552 100644 --- a/app/Filament/Admin/Resources/ResultResource.php +++ b/app/Filament/Admin/Resources/ResultResource.php @@ -4,17 +4,13 @@ namespace App\Filament\Admin\Resources; -use App\Enums\GeneralStatus; -use App\Filament\Admin\Resources\ResultResource\Pages; +use App\Filament\Admin\Schemas\ResultResourceSchema; +use App\Filament\Admin\Resources\ResultResource\Pages\ListResults; +use App\Filament\Admin\Resources\ResultResource\Pages\CreateResult; +use App\Filament\Admin\Resources\ResultResource\Pages\EditResult; use App\Models\Result; -use App\Tables\Actions\EditAction; -use App\Tables\Filters\SelectFilter; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables\Actions\CreateAction; -use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; class ResultResource extends Resource @@ -23,62 +19,24 @@ class ResultResource extends Resource protected static bool $shouldRegisterNavigation = false; - protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-rectangle-stack'; - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - Section::make() - ->maxWidth('3xl') - ->description(__('nomenclature.helper_texts.result')) - ->schema([ - TextInput::make('name') - ->label(__('nomenclature.labels.result_name')) - ->maxLength(200), - ]), - ]); + return ResultResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->heading(__('nomenclature.headings.results_table')) - ->headerActions([ - CreateAction::make() - ->label(__('nomenclature.actions.add_result')), - ]) - ->columns([ - TextColumn::make('name') - ->label(__('nomenclature.labels.result_name')), - - TextColumn::make('institutions_count') - ->label(__('nomenclature.labels.institutions')), - - TextColumn::make('organizations_count') - ->label(__('nomenclature.labels.centers')), - - TextColumn::make('status') - ->label(__('nomenclature.labels.status')), - ]) - ->filters([ - SelectFilter::make('status') - ->options(GeneralStatus::options()), - ]) - ->actions([ - EditAction::make(), - ]) - ->emptyStateHeading(__('nomenclature.headings.empty_state_results_table')) - ->emptyStateDescription(null) - ->emptyStateIcon('heroicon-o-clipboard-document-check'); + return ResultResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListResults::route('/'), - 'create' => Pages\CreateResult::route('/create'), - 'edit' => Pages\EditResult::route('/{record}/edit'), + 'index' => ListResults::route('/'), + 'create' => CreateResult::route('/create'), + 'edit' => EditResult::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Admin/Resources/ResultResource/Pages/EditResult.php b/app/Filament/Admin/Resources/ResultResource/Pages/EditResult.php index 7d7d3af5..be47b997 100644 --- a/app/Filament/Admin/Resources/ResultResource/Pages/EditResult.php +++ b/app/Filament/Admin/Resources/ResultResource/Pages/EditResult.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\ResultResource\Pages; +use Filament\Actions\DeleteAction; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Actions\ChangeNomenclatureStatusAction; @@ -39,7 +40,7 @@ protected function getHeaderActions(): array ChangeNomenclatureStatusAction::make(), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('nomenclature.actions.delete_result')) ->modalHeading(__('nomenclature.headings.delete_result_modal_heading')) ->outlined() diff --git a/app/Filament/Admin/Resources/ResultResource/Pages/ListResults.php b/app/Filament/Admin/Resources/ResultResource/Pages/ListResults.php index 73f6f8cf..c68f63d6 100644 --- a/app/Filament/Admin/Resources/ResultResource/Pages/ListResults.php +++ b/app/Filament/Admin/Resources/ResultResource/Pages/ListResults.php @@ -12,7 +12,7 @@ class ListResults extends ManageRecords { protected static string $resource = ResultResource::class; - protected static string $view = 'filament.admin.pages.nomenclature-list'; + protected string $view = 'filament.admin.pages.nomenclature-list'; public function getTitle(): string|Htmlable { diff --git a/app/Filament/Admin/Resources/RoleResource.php b/app/Filament/Admin/Resources/RoleResource.php index 859dcd05..85f651b2 100644 --- a/app/Filament/Admin/Resources/RoleResource.php +++ b/app/Filament/Admin/Resources/RoleResource.php @@ -4,25 +4,15 @@ namespace App\Filament\Admin\Resources; -use App\Enums\AdminPermission; -use App\Enums\CasePermission; -use App\Enums\GeneralStatus; -use App\Filament\Admin\Resources\RoleResource\Pages; -use App\Forms\Components\Spacer; +use App\Filament\Admin\Schemas\RoleResourceSchema; +use App\Filament\Admin\Resources\RoleResource\Pages\ListRoles; +use App\Filament\Admin\Resources\RoleResource\Pages\CreateRole; +use App\Filament\Admin\Resources\RoleResource\Pages\ViewRole; +use App\Filament\Admin\Resources\RoleResource\Pages\EditRole; use App\Models\Role; -use App\Tables\Actions\EditAction; -use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables\Actions\CreateAction; -use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; class RoleResource extends Resource { @@ -30,87 +20,14 @@ class RoleResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - Section::make() - ->maxWidth('3xl') - ->schema([ - Placeholder::make('description') - ->hiddenLabel() - ->content(__('nomenclature.helper_texts.role_page_description')), - - TextInput::make('name') - ->label(__('nomenclature.labels.role_name')) - ->placeholder(__('nomenclature.placeholders.role_name')) - ->maxLength(200), - - Toggle::make('case_manager') - ->label(__('nomenclature.labels.role_case_manager')), - - Spacer::make(), - - Placeholder::make(__('nomenclature.helper_texts.role_page_default_permissions')), - - CheckboxList::make('case_permissions') - ->label(__('nomenclature.labels.case_permissions')) - ->options(CasePermission::getOptionsWithoutCaseManager()) - ->columnSpanFull(), - - CheckboxList::make('ngo_admin_permissions') - ->label(__('nomenclature.labels.ngo_admin_permissions')) - ->options(AdminPermission::options()) - ->columnSpanFull(), - - ]), - ]); + return RoleResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing( - fn (Builder $query) => $query - ->withCount(['users']) - ->with(['organizations']) - ) - ->heading(__('nomenclature.headings.roles_table')) - ->headerActions([ - CreateAction::make() - ->label(__('nomenclature.actions.add_role')), - - ]) - ->columns([ - TextColumn::make('name') - ->label(__('nomenclature.labels.role_name')), - - TextColumn::make('institutions') - ->label(__('nomenclature.labels.institutions')) - ->formatStateUsing(fn ($record) => $record->organizations->unique('institution_id')->count()) - ->default(0), - - TextColumn::make('organizations') - ->label(__('nomenclature.labels.centers')) - ->default(0) - ->formatStateUsing(fn ($record) => $record->organizations?->unique()->count()), - - TextColumn::make('users_count') - ->label(__('nomenclature.labels.users')), - - TextColumn::make('status') - ->label(__('nomenclature.labels.status')), - ]) - ->filters([ - SelectFilter::make('status') - ->options(GeneralStatus::options()), - ]) - ->actions([ - EditAction::make(), - ]) - ->emptyStateHeading(__('nomenclature.labels.empty_state_role_table')) - ->emptyStateDescription(null) - ->emptyStateIcon('heroicon-o-clipboard-document-check'); + return RoleResourceSchema::table($table); } public static function getRelations(): array @@ -123,10 +40,10 @@ public static function getRelations(): array public static function getPages(): array { return [ - 'index' => Pages\ListRoles::route('/'), - 'create' => Pages\CreateRole::route('/create'), - 'view' => Pages\ViewRole::route('/{record}'), - 'edit' => Pages\EditRole::route('/{record}/edit'), + 'index' => ListRoles::route('/'), + 'create' => CreateRole::route('/create'), + 'view' => ViewRole::route('/{record}'), + 'edit' => EditRole::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Admin/Resources/RoleResource/Pages/ListRoles.php b/app/Filament/Admin/Resources/RoleResource/Pages/ListRoles.php index 399ef9d8..60cfb268 100644 --- a/app/Filament/Admin/Resources/RoleResource/Pages/ListRoles.php +++ b/app/Filament/Admin/Resources/RoleResource/Pages/ListRoles.php @@ -12,7 +12,7 @@ class ListRoles extends ManageRecords { protected static string $resource = RoleResource::class; - protected static string $view = 'filament.admin.pages.nomenclature-list'; + protected string $view = 'filament.admin.pages.nomenclature-list'; public function getTitle(): string|Htmlable { diff --git a/app/Filament/Admin/Resources/RoleResource/Pages/ViewRole.php b/app/Filament/Admin/Resources/RoleResource/Pages/ViewRole.php index 496a9449..c726f705 100644 --- a/app/Filament/Admin/Resources/RoleResource/Pages/ViewRole.php +++ b/app/Filament/Admin/Resources/RoleResource/Pages/ViewRole.php @@ -4,10 +4,12 @@ namespace App\Filament\Admin\Resources\RoleResource\Pages; +use Filament\Actions\EditAction; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Filament\Admin\Resources\RoleResource; use Filament\Actions; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -36,14 +38,14 @@ protected function getHeaderActions(): array BackAction::make() ->url(RoleResource::getUrl()), - Actions\EditAction::make() + EditAction::make() ->label(__('nomenclature.actions.edit_role')), ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') ->columns() diff --git a/app/Filament/Admin/Resources/ServiceResource.php b/app/Filament/Admin/Resources/ServiceResource.php index 65bd420b..e230cd73 100644 --- a/app/Filament/Admin/Resources/ServiceResource.php +++ b/app/Filament/Admin/Resources/ServiceResource.php @@ -4,29 +4,15 @@ namespace App\Filament\Admin\Resources; -use App\Enums\CounselingSheet; -use App\Enums\GeneralStatus; -use App\Filament\Admin\Resources\ServiceResource\Pages; +use App\Filament\Admin\Schemas\ServiceResourceSchema; +use App\Filament\Admin\Resources\ServiceResource\Pages\ListServices; +use App\Filament\Admin\Resources\ServiceResource\Pages\ViewService; +use App\Filament\Admin\Resources\ServiceResource\Pages\EditService; use App\Filament\Admin\Resources\ServiceResource\Pages\CreateService; -use App\Forms\Components\Select; -use App\Forms\Components\TableRepeater; use App\Models\Service; -use App\Models\ServiceIntervention; -use Awcodes\TableRepeater\Header; -use Filament\Forms\Components\Actions\Action; -use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Form; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Support\Enums\Alignment; -use Filament\Tables\Actions\CreateAction; -use Filament\Tables\Actions\ViewAction; -use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; class ServiceResource extends Resource { @@ -54,152 +40,23 @@ public static function getPluralModelLabel(): string return __('service.label.plural'); } - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - Section::make() - ->maxWidth('3xl') - ->schema([ - TextInput::make('name') - ->label(__('service.field.name')) - ->columnSpanFull() - ->maxLength(200) - ->required(), - - Select::make('counseling_sheet') - ->label(__('nomenclature.labels.counseling_sheet')) - ->options(CounselingSheet::options()), - - ]), - - Section::make() - ->schema([ - TableRepeater::make('serviceInterventions') - ->relationship('serviceInterventions') - ->label(__('nomenclature.headings.service_intervention')) - ->helperText(__('nomenclature.helper_texts.service_interventions')) - ->reorderable() - ->orderColumn() - ->columnSpanFull() - ->addActionLabel(__('nomenclature.actions.add_intervention')) - ->minItems(1) - ->showLabels() - ->headers([ - Header::make('index') - ->label(__('nomenclature.labels.nr')) - ->width('2em') - ->align(Alignment::Right), - - Header::make('name') - ->label(__('nomenclature.labels.intervention_name')) - ->markAsRequired(), - - Header::make('status') - ->label(__('nomenclature.labels.status')), - ]) - ->schema([ - Placeholder::make('index') - ->label(__('nomenclature.labels.nr')) - ->content(function () { - static $index = 1; - - return $index++; - }) - ->hiddenLabel(), - - TextInput::make('name') - ->label(__('nomenclature.labels.intervention_name')) - ->hiddenLabel() - ->maxLength(200) - ->required(), - - Toggle::make('status') - ->live() - ->default(true) - ->afterStateUpdated(function (bool $state) { - if (! $state) { - // TODO: fix this - dd('Modal cu inactivare de hard confirmation'); - } - }) - ->label( - fn (bool $state) => $state - ? __('nomenclature.labels.active') - : __('nomenclature.labels.inactive') - ), - ]) - ->deleteAction( - fn (Action $action) => $action - ->disabled(function (array $arguments, TableRepeater $component, string $operation): bool { - if ($operation === 'create') { - return false; - } - - $items = $component->getState(); - $currentItem = $items[$arguments['item']]; - - $serviceIntervention = ServiceIntervention::where('id', $currentItem['id']) - ->withCount('organizationIntervention') - ->first(); - - if (! $serviceIntervention) { - return false; - } - - return $serviceIntervention->organization_intervention_count > 0; - }) - ), - ]), - ]); + return ServiceResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing(fn (Builder $query) => $query->withCount(['organizationServices'])) - ->columns([ - TextColumn::make('name') - ->label(__('nomenclature.labels.name')) - ->searchable(), - - TextColumn::make('institutions_count') - ->label(__('nomenclature.labels.institutions')), - - TextColumn::make('organization_services_count') - ->label(__('nomenclature.labels.centers')), - - TextColumn::make('status') - ->label(__('nomenclature.labels.status')) - ->badge(), - ]) - ->actions([ - ViewAction::make() - ->label(__('general.action.view_details')) - ->url(fn (Service $record) => ServiceResource::getUrl('view', ['record' => $record])), - ]) - ->headerActions([ - CreateAction::make() - ->label(__('nomenclature.actions.add_service')) - ->url(self::getUrl('create')), - ]) - ->filters([ - SelectFilter::make('status') - ->options(GeneralStatus::options()), - ]) - ->heading(__('nomenclature.headings.service_table')) - ->emptyStateHeading(__('nomenclature.labels.empty_state_service_table')) - ->emptyStateDescription(null) - ->emptyStateIcon('heroicon-o-clipboard-document-check'); + return ServiceResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListServices::route('/'), + 'index' => ListServices::route('/'), 'create' => CreateService::route('/create'), - 'view' => Pages\ViewService::route('/{record}'), - 'edit' => Pages\EditService::route('/{record}/edit'), + 'view' => ViewService::route('/{record}'), + 'edit' => EditService::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Admin/Resources/ServiceResource/Pages/ListServices.php b/app/Filament/Admin/Resources/ServiceResource/Pages/ListServices.php index 59b39a4e..9249b993 100644 --- a/app/Filament/Admin/Resources/ServiceResource/Pages/ListServices.php +++ b/app/Filament/Admin/Resources/ServiceResource/Pages/ListServices.php @@ -12,7 +12,7 @@ class ListServices extends ManageRecords { protected static string $resource = ServiceResource::class; - protected static string $view = 'filament.admin.pages.nomenclature-list'; + protected string $view = 'filament.admin.pages.nomenclature-list'; public function getTitle(): string|Htmlable { diff --git a/app/Filament/Admin/Resources/ServiceResource/Pages/ViewService.php b/app/Filament/Admin/Resources/ServiceResource/Pages/ViewService.php index e607313d..4bf75a88 100644 --- a/app/Filament/Admin/Resources/ServiceResource/Pages/ViewService.php +++ b/app/Filament/Admin/Resources/ServiceResource/Pages/ViewService.php @@ -4,6 +4,8 @@ namespace App\Filament\Admin\Resources\ServiceResource\Pages; +use Filament\Actions\EditAction; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Enums\CounselingSheet; use App\Filament\Admin\Resources\ServiceResource; @@ -14,7 +16,7 @@ use Filament\Actions; use Filament\Actions\StaticAction; use Filament\Infolists\Components\Actions\Action; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -43,14 +45,14 @@ protected function getActions(): array BackAction::make() ->url(ServiceResource::getUrl()), - Actions\EditAction::make() + EditAction::make() ->label(__('nomenclature.actions.edit_service')), ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->visible(fn (Service $record) => $record->counseling_sheet) ->maxWidth('3xl') @@ -59,10 +61,10 @@ public function infolist(Infolist $infolist): Infolist ->state(__('service.helper_texts.counseling_sheet')) ->icon('heroicon-o-document-text') ->action( - Action::make('view_counseling_sheet') + \Filament\Actions\Action::make('view_counseling_sheet') ->label(__('service.actions.view_counseling_sheet')) ->modalHeading(fn (Service $record) => $record->counseling_sheet?->getLabel()) - ->form(fn (Service $record) => match ($record->counseling_sheet) { + ->schema(fn (Service $record) => match ($record->counseling_sheet) { CounselingSheet::LEGAL_ASSISTANCE => EditCounselingSheet::getLegalAssistanceForm(), CounselingSheet::PSYCHOLOGICAL_ASSISTANCE => EditCounselingSheet::getSchemaForPsychologicalAssistance(), CounselingSheet::SOCIAL_ASSISTANCE => EditCounselingSheet::getSchemaForSocialAssistance(), @@ -70,7 +72,7 @@ public function infolist(Infolist $infolist): Infolist }) ->disabledForm() ->modalAutofocus(false) - ->modalSubmitAction(fn (StaticAction $action) => $action->hidden()) + ->modalSubmitAction(fn (\Filament\Actions\Action $action) => $action->hidden()) ->link(), ), ]), diff --git a/app/Filament/Admin/Resources/UserInstitutionResource.php b/app/Filament/Admin/Resources/UserInstitutionResource.php index ef1ee5ba..f1f86abd 100644 --- a/app/Filament/Admin/Resources/UserInstitutionResource.php +++ b/app/Filament/Admin/Resources/UserInstitutionResource.php @@ -4,24 +4,12 @@ namespace App\Filament\Admin\Resources; -use App\Filament\Admin\Resources\UserInstitutionResource\Pages; -use App\Models\User; -use Filament\Resources\Resource; - -class UserInstitutionResource extends Resource +/** + * @deprecated This resource has been moved to InstitutionResource\Resources\UserInstitutionResource + * Use App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource instead + */ +class UserInstitutionResource extends \App\Filament\Admin\Resources\InstitutionResource\Resources\UserInstitutionResource { - protected static ?string $model = User::class; - - public static string $parentResource = InstitutionResource::class; - - protected static bool $shouldRegisterNavigation = false; - - protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - - public static function getPages(): array - { - return [ - 'index' => Pages\ListUserInstitutions::route('/'), - ]; - } + // This class is kept for backward compatibility + // All functionality has been moved to InstitutionResource\Resources\UserInstitutionResource } diff --git a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/EditUserInstitution.php b/app/Filament/Admin/Resources/UserInstitutionResource/Pages/EditUserInstitution.php deleted file mode 100644 index f319efcb..00000000 --- a/app/Filament/Admin/Resources/UserInstitutionResource/Pages/EditUserInstitution.php +++ /dev/null @@ -1,99 +0,0 @@ - $this->parent, - 'activeRelationManager' => 'admins', - ]); - } - - public function getBreadcrumbs(): array - { - return [ - InstitutionResource::getUrl() => __('institution.headings.list_title'), - InstitutionResource::getUrl('view', ['record' => $this->parent]) => $this->parent->name, - InstitutionResource::getUrl('user.view', [ - 'parent' => $this->parent, - 'record' => $this->getRecord(), - ]) => $this->getRecord()->full_name, - ]; - } - - public function getTitle(): string|Htmlable - { - return $this->getRecord()->full_name; - } - - public function getHeaderActions(): array - { - return [ - BackAction::make() - ->url($this->getRedirectUrl()), - ]; - } - - public function form(Form $form): Form - { - return $form->schema([ - Section::make() - ->maxWidth('3xl') - ->columns() - ->schema(self::getSchema()), - ]); - } - - public static function getSchema(): array - { - return [ - TextInput::make('first_name') - ->label(__('institution.labels.first_name')) - ->placeholder(__('institution.placeholders.first_name')) - ->maxLength(50) - ->required(), - - TextInput::make('last_name') - ->label(__('institution.labels.last_name')) - ->placeholder(__('institution.placeholders.last_name')) - ->maxLength(50) - ->required(), - - TextInput::make('email') - ->label(__('institution.labels.email')) - ->placeholder(__('institution.placeholders.email')) - ->maxLength(50) - ->email() - ->unique() - ->required(), - - TextInput::make('phone') - ->label(__('institution.labels.phone')) - ->placeholder(__('institution.placeholders.phone')) - ->maxLength(14) - ->tel() - ->required(), - ]; - } -} diff --git a/app/Filament/Admin/Resources/UserResource.php b/app/Filament/Admin/Resources/UserResource.php index 021f314d..05946568 100644 --- a/app/Filament/Admin/Resources/UserResource.php +++ b/app/Filament/Admin/Resources/UserResource.php @@ -4,27 +4,20 @@ namespace App\Filament\Admin\Resources; -use App\Filament\Admin\Resources\UserResource\Pages; -use App\Forms\Components\Select; +use App\Filament\Admin\Schemas\UserResourceSchema; +use App\Filament\Admin\Resources\UserResource\Pages\ListUsers; +use App\Filament\Admin\Resources\UserResource\Pages\CreateUser; +use App\Filament\Admin\Resources\UserResource\Pages\EditUser; use App\Models\User; -use App\Tables\Actions\EditAction; -use Filament\Forms\Components\Radio; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables; -use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Filters\SelectFilter; -use Filament\Tables\Filters\TernaryFilter; use Filament\Tables\Table; class UserResource extends Resource { protected static ?string $model = User::class; - protected static ?string $navigationIcon = 'heroicon-o-user-group'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-user-group'; protected static ?string $tenantOwnershipRelationshipName = 'organizations'; @@ -42,98 +35,14 @@ public static function getPluralModelLabel(): string return __('user.label.plural'); } - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->inlineLabel() - ->schema([ - Section::make() - ->maxWidth('3xl') - ->schema([ - TextInput::make('first_name') - ->label(__('field.first_name')) - ->maxLength(100) - ->required(), - - TextInput::make('last_name') - ->label(__('field.last_name')) - ->maxLength(100) - ->required(), - - TextInput::make('email') - ->label(__('field.email')) - ->unique(ignoreRecord: true) - ->columnSpanFull() - ->maxLength(200) - ->email() - ->required(), - ]), - - Section::make() - ->maxWidth('3xl') - // ->columns() - ->schema([ - Radio::make('is_admin') - ->label(__('field.role')) - ->inlineLabel() - ->boolean( - trueLabel: __('user.role.admin'), - falseLabel: __('user.role.user'), - ) - ->default(false) - ->live(), - - Select::make('organizations') - ->relationship('organizations', titleAttribute: 'name') - ->label(__('field.organizations')) - ->inlineLabel() - ->visible(fn (Get $get) => \boolval($get('is_admin')) === false) - ->multiple() - ->preload() - ->required(), - ]), - ]); + return UserResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->columns([ - TextColumn::make('first_name') - ->searchable(), - - TextColumn::make('last_name') - ->searchable(), - - TextColumn::make('organizations.name') - ->wrap(), - - TextColumn::make('is_admin') - ->label(__('field.role')), - - TextColumn::make('account_status'), - - TextColumn::make('last_login_at') - ->sortable(), - ]) - ->filters([ - TernaryFilter::make('is_admin') - ->label(__('field.role')) - ->trueLabel(__('user.role.admin')) - ->falseLabel(__('user.role.user')), - - SelectFilter::make('organizations') - ->relationship('organizations', 'name') - ->multiple(), - ]) - ->actions([ - EditAction::make(), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]); + return UserResourceSchema::table($table); } public static function getRelations(): array @@ -146,9 +55,9 @@ public static function getRelations(): array public static function getPages(): array { return [ - 'index' => Pages\ListUsers::route('/'), - 'create' => Pages\CreateUser::route('/create'), - 'edit' => Pages\EditUser::route('/{record}/edit'), + 'index' => ListUsers::route('/'), + 'create' => CreateUser::route('/create'), + 'edit' => EditUser::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Admin/Resources/UserResource/Pages/EditUser.php b/app/Filament/Admin/Resources/UserResource/Pages/EditUser.php index a914d9d1..e89d9d9d 100644 --- a/app/Filament/Admin/Resources/UserResource/Pages/EditUser.php +++ b/app/Filament/Admin/Resources/UserResource/Pages/EditUser.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\UserResource\Pages; +use Filament\Actions\DeleteAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Admin\Resources\UserResource; use Filament\Actions; @@ -18,7 +19,7 @@ class EditUser extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + DeleteAction::make(), ]; } } diff --git a/app/Filament/Admin/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Admin/Resources/UserResource/Pages/ListUsers.php index 7f6d59a2..cc9ce37c 100644 --- a/app/Filament/Admin/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Admin/Resources/UserResource/Pages/ListUsers.php @@ -4,6 +4,7 @@ namespace App\Filament\Admin\Resources\UserResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Admin\Resources\UserResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListUsers extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Admin/Schemas/BenefitResourceSchema.php b/app/Filament/Admin/Schemas/BenefitResourceSchema.php new file mode 100644 index 00000000..69323811 --- /dev/null +++ b/app/Filament/Admin/Schemas/BenefitResourceSchema.php @@ -0,0 +1,139 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->headerActions(self::getTableHeaderActions()) + ->heading(__('nomenclature.headings.benefit_table')) + ->columns(self::getTableColumns()) + ->recordActions(self::getTableActions()) + ->filters(self::getTableFilters()) + ->emptyStateHeading(__('nomenclature.headings.empty_state_benefit_table')) + ->emptyStateDescription(null) + ->emptyStateIcon('heroicon-o-clipboard-document-check'); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->schema([ + TextInput::make('name') + ->label(__('nomenclature.labels.benefit_name')) + ->maxWidth('3xl') + ->maxLength(200) + ->required(), + + Repeater::make('benefitTypes') + ->relationship('benefitTypes') + ->label(__('nomenclature.headings.benefit_types')) + ->helperText(__('nomenclature.helper_texts.benefit_types')) + ->reorderable() + ->orderColumn('sort') + ->columnSpanFull() + ->minItems(1) + ->addActionLabel(__('nomenclature.actions.add_benefit_type')) + ->schema([ + TextInput::make('name') + ->label(__('nomenclature.labels.benefit_type_name')) + ->maxLength(200) + ->required() + ->columnSpan(2), + + Toggle::make('status') + ->label(__('nomenclature.labels.status')) + ->live() + ->default(true) + ->formatStateUsing(fn ($state) => $state ?? true) + ->dehydrated(), + ]) + ->columns(3) + ->itemLabel(fn (array $state): ?string => $state['name'] ?? null) + ->collapsible() + ->deleteAction( + fn (\Filament\Actions\Action $action) => $action + ->disabled(function (array $arguments, Repeater $component): bool { + $items = $component->getState(); + $currentItem = $items[$arguments['item']] ?? null; + + if (! isset($currentItem['id'])) { + return false; + } + + return (bool) BenefitService::query() + ->whereJsonContains('benefit_types', \sprintf('%s', $currentItem['id'])) + ->count(); + }) + ), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('name') + ->label(__('nomenclature.labels.benefit')), + + TextColumn::make('institutions_count') + ->label(__('nomenclature.labels.institutions')), + + TextColumn::make('organizations_count') + ->label(__('nomenclature.labels.centers')), + + TextColumn::make('status') + ->label(__('nomenclature.labels.status')), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->label(__('general.action.view_details')) + ->url(fn (Benefit $record) => \App\Filament\Admin\Resources\BenefitResource::getUrl('view', ['record' => $record])), + ]; + } + + public static function getTableHeaderActions(): array + { + return [ + CreateAction::make() + ->label(__('nomenclature.actions.add_benefit')) + ->url(\App\Filament\Admin\Resources\BenefitResource::getUrl('create')), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('status') + ->options(GeneralStatus::options()), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/InstitutionResourceSchema.php b/app/Filament/Admin/Schemas/InstitutionResourceSchema.php new file mode 100644 index 00000000..b951bd09 --- /dev/null +++ b/app/Filament/Admin/Schemas/InstitutionResourceSchema.php @@ -0,0 +1,271 @@ +components([]); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing( + fn (Builder $query) => $query + ->withCount(['organizations', 'beneficiaries', 'users']) + ->with(['county', 'city']) + ) + ->defaultSort('created_at', 'desc') + ->columns(self::getTableColumns()) + ->filters([]) + ->recordActions(self::getTableActions()) + ->heading(__('institution.headings.all_institutions')) + ->description(trans_choice('institution.headings.count', Institution::count(), ['count' => Institution::count()])) + ->emptyStateIcon('heroicon-o-clipboard-document-list') + ->emptyStateHeading(__('institution.headings.empty_state')) + ->emptyStateDescription(null); + } + + public static function getFormSchemaForDetails(): array + { + return [ + \Filament\Schemas\Components\Section::make() + ->maxWidth('3xl') + ->columns() + ->schema([ + \Filament\Forms\Components\TextInput::make('name') + ->label(__('organization.field.name')) + ->placeholder(__('organization.placeholders.name')) + ->maxLength(200) + ->required(), + + \Filament\Forms\Components\TextInput::make('short_name') + ->label(__('organization.field.short_name')) + ->placeholder(__('organization.placeholders.short_name')) + ->maxLength(50), + + \App\Forms\Components\Select::make('type') + ->label(__('organization.field.type')) + ->placeholder(__('organization.placeholders.type')) + ->options(\App\Enums\OrganizationType::options()) + ->enum(\App\Enums\OrganizationType::class) + ->required(), + + \Filament\Forms\Components\TextInput::make('cif') + ->label(__('organization.field.cif')) + ->placeholder(__('organization.placeholders.cif')) + ->required(), + + \Filament\Forms\Components\TextInput::make('main_activity') + ->label(__('organization.field.main_activity')) + ->placeholder(__('organization.placeholders.main_activity')) + ->maxLength(200) + ->required(), + + \App\Forms\Components\Select::make('area') + ->label(__('organization.field.area')) + ->placeholder(__('organization.placeholders.area')) + ->options(\App\Enums\AreaType::options()) + ->required(), + + \App\Forms\Components\Location::make() + ->city() + ->address() + ->countyLabel(__('organization.field.county')) + ->cityLabel(__('organization.field.city')) + ->addressLabel(__('organization.field.address')) + ->addressMaxLength(200) + ->addressColumnSpanFull() + ->required(), + + \Filament\Schemas\Components\Grid::make() + ->schema([ + \Filament\Forms\Components\TextInput::make('representative_person.name') + ->label(__('organization.field.representative_name')) + ->placeholder(__('organization.placeholders.representative_name')) + ->maxLength(50) + ->required(), + + \Filament\Forms\Components\TextInput::make('representative_person.email') + ->label(__('organization.field.representative_email')) + ->placeholder(__('organization.placeholders.representative_email')) + ->maxLength(50) + ->email(), + + \Filament\Forms\Components\TextInput::make('representative_person.phone') + ->label(__('organization.field.representative_phone')) + ->placeholder(__('organization.placeholders.representative_phone')) + ->maxLength(13) + ->tel(), + ])->columnSpanFull(), + + \Filament\Schemas\Components\Grid::make() + ->schema([ + \Filament\Forms\Components\TextInput::make('contact_person.name') + ->label(__('organization.field.contact_person')) + ->placeholder(__('organization.placeholders.contact_person')) + ->maxLength(50) + ->required(), + + \Filament\Forms\Components\TextInput::make('contact_person.email') + ->label(__('organization.field.contact_person_email')) + ->placeholder(__('organization.placeholders.contact_person_email')) + ->maxLength(50) + ->required() + ->email(), + + \Filament\Forms\Components\TextInput::make('contact_person.phone') + ->label(__('organization.field.contact_person_phone')) + ->placeholder(__('organization.placeholders.contact_person_phone')) + ->maxLength(13) + ->tel() + ->required(), + ])->columnSpanFull(), + + \Filament\Forms\Components\TextInput::make('website') + ->label(__('organization.field.website')) + ->placeholder(__('organization.placeholders.website')) + ->maxLength(200) + ->url(), + + \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('organization_status') + ->label(__('institution.labels.organization_status')) + ->maxSize(config('media-library.max_file_size')) + ->helperText(__('institution.helper_texts.organization_status')) + ->collection('organization_status') + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'application/pdf', + 'image/*', + ]) + ->columnSpanFull() + ->required(), + + \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('social_service_provider_certificate') + ->label(__('institution.labels.social_service_provider_certificate')) + ->maxSize(config('media-library.max_file_size')) + ->helperText(__('institution.helper_texts.social_service_provider_certificate')) + ->collection('social_service_provider_certificate') + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'application/pdf', + 'image/*', + ]) + ->columnSpanFull(), + ]), + ]; + } + + public static function getFormSchemaForCenters(): array + { + return [ + \App\Forms\Components\Repeater::make('organizations') + ->maxWidth('3xl') + ->hiddenLabel() + ->columns() + ->minItems(1) + ->relationship('organizations') + ->addActionLabel(__('institution.actions.add_organization')) + ->schema([ + \Filament\Forms\Components\TextInput::make('name') + ->label(__('institution.labels.center_name')) + ->placeholder(__('organization.placeholders.center_name')) + ->maxLength(200) + ->required(), + + \Filament\Forms\Components\TextInput::make('short_name') + ->label(__('organization.field.short_name')) + ->placeholder(__('organization.placeholders.center_short_name')) + ->maxLength(50), + + \Filament\Forms\Components\TextInput::make('main_activity') + ->label(__('organization.field.main_activity')) + ->placeholder(__('organization.placeholders.main_activity')) + ->columnSpanFull() + ->maxLength(200) + ->required(), + + \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('social_service_licensing_certificate') + ->label(__('institution.labels.social_service_licensing_certificate')) + ->helperText(__('institution.helper_texts.social_service_licensing_certificate')) + ->maxSize(config('media-library.max_file_size')) + ->collection('social_service_licensing_certificate') + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'application/pdf', + 'image/*', + ]) + ->columnSpanFull(), + + \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('logo') + ->label(__('institution.labels.logo_center')) + ->helperText(__('institution.helper_texts.logo')) + ->maxSize(config('media-library.max_file_size')) + ->collection('logo') + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'image/*', + ]) + ->columnSpanFull(), + + \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('organization_header') + ->label(__('institution.labels.organization_header')) + ->helperText(__('institution.helper_texts.organization_header')) + ->maxSize(config('media-library.max_file_size')) + ->collection('organization_header') + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'image/*', + ]) + ->columnSpanFull(), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('name') + ->label(__('institution.headings.institution_name')), + + TextColumn::make('county_and_city') + ->label(__('institution.headings.registered_office')), + + TextColumn::make('organizations_count') + ->label(__('institution.headings.centers')), + + TextColumn::make('beneficiaries_count') + ->label(__('institution.headings.cases')), + + TextColumn::make('users_count') + ->label(__('institution.headings.specialists')), + + TextColumn::make('status') + ->label(__('institution.headings.status')), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->label(__('general.action.view_details')), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/ResultResourceSchema.php b/app/Filament/Admin/Schemas/ResultResourceSchema.php new file mode 100644 index 00000000..9a429a49 --- /dev/null +++ b/app/Filament/Admin/Schemas/ResultResourceSchema.php @@ -0,0 +1,90 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->heading(__('nomenclature.headings.results_table')) + ->headerActions(self::getTableHeaderActions()) + ->columns(self::getTableColumns()) + ->filters(self::getTableFilters()) + ->recordActions(self::getTableActions()) + ->emptyStateHeading(__('nomenclature.headings.empty_state_results_table')) + ->emptyStateDescription(null) + ->emptyStateIcon('heroicon-o-clipboard-document-check'); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->maxWidth('3xl') + ->description(__('nomenclature.helper_texts.result')) + ->schema([ + TextInput::make('name') + ->label(__('nomenclature.labels.result_name')) + ->maxLength(200), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('name') + ->label(__('nomenclature.labels.result_name')), + + TextColumn::make('institutions_count') + ->label(__('nomenclature.labels.institutions')), + + TextColumn::make('organizations_count') + ->label(__('nomenclature.labels.centers')), + + TextColumn::make('status') + ->label(__('nomenclature.labels.status')), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('status') + ->options(GeneralStatus::options()), + ]; + } + + public static function getTableActions(): array + { + return [ + EditAction::make(), + ]; + } + + public static function getTableHeaderActions(): array + { + return [ + CreateAction::make() + ->label(__('nomenclature.actions.add_result')), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/RoleResourceSchema.php b/app/Filament/Admin/Schemas/RoleResourceSchema.php new file mode 100644 index 00000000..1c839de8 --- /dev/null +++ b/app/Filament/Admin/Schemas/RoleResourceSchema.php @@ -0,0 +1,131 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing( + fn (Builder $query) => $query + ->withCount(['users']) + ->with(['organizations']) + ) + ->heading(__('nomenclature.headings.roles_table')) + ->headerActions(self::getTableHeaderActions()) + ->columns(self::getTableColumns()) + ->filters(self::getTableFilters()) + ->recordActions(self::getTableActions()) + ->emptyStateHeading(__('nomenclature.labels.empty_state_role_table')) + ->emptyStateDescription(null) + ->emptyStateIcon('heroicon-o-clipboard-document-check'); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->maxWidth('3xl') + ->schema([ + Placeholder::make('description') + ->hiddenLabel() + ->content(__('nomenclature.helper_texts.role_page_description')), + + TextInput::make('name') + ->label(__('nomenclature.labels.role_name')) + ->placeholder(__('nomenclature.placeholders.role_name')) + ->maxLength(200), + + Toggle::make('case_manager') + ->label(__('nomenclature.labels.role_case_manager')), + + Spacer::make(), + + Placeholder::make(__('nomenclature.helper_texts.role_page_default_permissions')), + + CheckboxList::make('case_permissions') + ->label(__('nomenclature.labels.case_permissions')) + ->options(CasePermission::getOptionsWithoutCaseManager()) + ->columnSpanFull(), + + CheckboxList::make('ngo_admin_permissions') + ->label(__('nomenclature.labels.ngo_admin_permissions')) + ->options(AdminPermission::options()) + ->columnSpanFull(), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('name') + ->label(__('nomenclature.labels.role_name')), + + TextColumn::make('institutions') + ->label(__('nomenclature.labels.institutions')) + ->formatStateUsing(fn ($record) => $record->organizations->unique('institution_id')->count()) + ->default(0), + + TextColumn::make('organizations') + ->label(__('nomenclature.labels.centers')) + ->default(0) + ->formatStateUsing(fn ($record) => $record->organizations?->unique()->count()), + + TextColumn::make('users_count') + ->label(__('nomenclature.labels.users')), + + TextColumn::make('status') + ->label(__('nomenclature.labels.status')), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('status') + ->options(GeneralStatus::options()), + ]; + } + + public static function getTableActions(): array + { + return [ + EditAction::make(), + ]; + } + + public static function getTableHeaderActions(): array + { + return [ + CreateAction::make() + ->label(__('nomenclature.actions.add_role')), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/ServiceResourceSchema.php b/app/Filament/Admin/Schemas/ServiceResourceSchema.php new file mode 100644 index 00000000..6b2882cd --- /dev/null +++ b/app/Filament/Admin/Schemas/ServiceResourceSchema.php @@ -0,0 +1,169 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing(fn (Builder $query) => $query->withCount(['organizationServices'])) + ->columns(self::getTableColumns()) + ->recordActions(self::getTableActions()) + ->headerActions(self::getTableHeaderActions()) + ->filters(self::getTableFilters()) + ->heading(__('nomenclature.headings.service_table')) + ->emptyStateHeading(__('nomenclature.labels.empty_state_service_table')) + ->emptyStateDescription(null) + ->emptyStateIcon('heroicon-o-clipboard-document-check'); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->maxWidth('3xl') + ->schema([ + TextInput::make('name') + ->label(__('service.field.name')) + ->columnSpanFull() + ->maxLength(200) + ->required(), + + Select::make('counseling_sheet') + ->label(__('nomenclature.labels.counseling_sheet')) + ->options(CounselingSheet::options()), + ]), + + Section::make() + ->schema([ + Repeater::make('serviceInterventions') + ->relationship('serviceInterventions') + ->label(__('nomenclature.headings.service_intervention')) + ->helperText(__('nomenclature.helper_texts.service_interventions')) + ->reorderable() + ->orderColumn('sort') + ->columnSpanFull() + ->addActionLabel(__('nomenclature.actions.add_intervention')) + ->minItems(1) + ->schema([ + TextEntry::make('index') + ->label(__('nomenclature.labels.nr')), + + TextInput::make('name') + ->label(__('nomenclature.labels.intervention_name')) + ->maxLength(200) + ->required() + ->columnSpan(2), + + Toggle::make('status') + ->label(__('nomenclature.labels.status')) + ->live() + ->default(true) + ->afterStateUpdated(function (bool $state) { + if (! $state) { + // TODO: fix this + dd('Modal cu inactivare de hard confirmation'); + } + }) + ->formatStateUsing(fn ($state) => $state ?? true) + ->dehydrated(), + ]) + ->columns(4) + ->itemLabel(fn (array $state): ?string => $state['name'] ?? null) + ->deleteAction( + fn (\Filament\Actions\Action $action) => $action + ->disabled(function (array $arguments, Repeater $component): bool { + $items = $component->getState(); + $currentItem = $items[$arguments['item']] ?? null; + + if (!isset($currentItem['id'])) { + return false; + } + + $serviceIntervention = ServiceIntervention::where('id', $currentItem['id']) + ->withCount('organizationIntervention') + ->first(); + + if (! $serviceIntervention) { + return false; + } + + return $serviceIntervention->organization_intervention_count > 0; + }) + ), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('name') + ->label(__('nomenclature.labels.name')) + ->searchable(), + + TextColumn::make('institutions_count') + ->label(__('nomenclature.labels.institutions')), + + TextColumn::make('organization_services_count') + ->label(__('nomenclature.labels.centers')), + + TextColumn::make('status') + ->label(__('nomenclature.labels.status')) + ->badge(), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->label(__('general.action.view_details')) + ->url(fn (Service $record) => \App\Filament\Admin\Resources\ServiceResource::getUrl('view', ['record' => $record])), + ]; + } + + public static function getTableHeaderActions(): array + { + return [ + CreateAction::make() + ->label(__('nomenclature.actions.add_service')) + ->url(\App\Filament\Admin\Resources\ServiceResource::getUrl('create')), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('status') + ->options(GeneralStatus::options()), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/UserInstitutionResourceSchema.php b/app/Filament/Admin/Schemas/UserInstitutionResourceSchema.php new file mode 100644 index 00000000..2dbc7043 --- /dev/null +++ b/app/Filament/Admin/Schemas/UserInstitutionResourceSchema.php @@ -0,0 +1,57 @@ +components([ + Section::make() + ->maxWidth('3xl') + ->columns() + ->schema(self::getFormComponents()), + ]); + } + + public static function getFormComponents(): array + { + return [ + TextInput::make('first_name') + ->label(__('institution.labels.first_name')) + ->placeholder(__('institution.placeholders.first_name')) + ->maxLength(50) + ->required(), + + TextInput::make('last_name') + ->label(__('institution.labels.last_name')) + ->placeholder(__('institution.placeholders.last_name')) + ->maxLength(50) + ->required(), + + TextInput::make('email') + ->label(__('institution.labels.email')) + ->placeholder(__('institution.placeholders.email')) + ->maxLength(50) + ->email() + ->unique() + ->required(), + + TextInput::make('phone') + ->label(__('institution.labels.phone')) + ->placeholder(__('institution.placeholders.phone')) + ->maxLength(14) + ->tel() + ->required(), + + \Filament\Forms\Components\Hidden::make('ngo_admin') + ->default(1), + ]; + } +} diff --git a/app/Filament/Admin/Schemas/UserResourceSchema.php b/app/Filament/Admin/Schemas/UserResourceSchema.php new file mode 100644 index 00000000..d2135d21 --- /dev/null +++ b/app/Filament/Admin/Schemas/UserResourceSchema.php @@ -0,0 +1,139 @@ +inlineLabel() + ->components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->columns(self::getTableColumns()) + ->filters(self::getTableFilters()) + ->recordActions(self::getTableActions()) + ->toolbarActions(self::getToolbarActions()); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->maxWidth('3xl') + ->schema([ + TextInput::make('first_name') + ->label(__('field.first_name')) + ->maxLength(100) + ->required(), + + TextInput::make('last_name') + ->label(__('field.last_name')) + ->maxLength(100) + ->required(), + + TextInput::make('email') + ->label(__('field.email')) + ->unique(ignoreRecord: true) + ->columnSpanFull() + ->maxLength(200) + ->email() + ->required(), + ]), + + Section::make() + ->maxWidth('3xl') + ->schema([ + Radio::make('is_admin') + ->label(__('field.role')) + ->inlineLabel() + ->boolean( + trueLabel: __('user.role.admin'), + falseLabel: __('user.role.user'), + ) + ->default(false) + ->live(), + + Select::make('organizations') + ->relationship('organizations', titleAttribute: 'name') + ->label(__('field.organizations')) + ->inlineLabel() + ->visible(fn (\Filament\Schemas\Components\Utilities\Get $get) => \boolval($get('is_admin')) === false) + ->multiple() + ->preload() + ->required(), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('first_name') + ->searchable(), + + TextColumn::make('last_name') + ->searchable(), + + TextColumn::make('organizations.name') + ->wrap(), + + TextColumn::make('is_admin') + ->label(__('field.role')), + + TextColumn::make('account_status'), + + TextColumn::make('last_login_at') + ->sortable(), + ]; + } + + public static function getTableFilters(): array + { + return [ + TernaryFilter::make('is_admin') + ->label(__('field.role')) + ->trueLabel(__('user.role.admin')) + ->falseLabel(__('user.role.user')), + + SelectFilter::make('organizations') + ->relationship('organizations', 'name') + ->multiple(), + ]; + } + + public static function getTableActions(): array + { + return [ + EditAction::make(), + ]; + } + + public static function getToolbarActions(): array + { + return [ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]; + } +} diff --git a/app/Filament/Admin/Widgets/UserActivity.php b/app/Filament/Admin/Widgets/UserActivity.php index d62ab2e9..692e6d35 100644 --- a/app/Filament/Admin/Widgets/UserActivity.php +++ b/app/Filament/Admin/Widgets/UserActivity.php @@ -11,11 +11,11 @@ class UserActivity extends ChartWidget { - protected static ?string $heading = 'Chart'; + protected ?string $heading = 'Chart'; protected int | string | array $columnSpan = 2; - protected static ?string $maxHeight = '300px'; + protected ?string $maxHeight = '300px'; protected function getData(): array { diff --git a/app/Filament/Organizations/Pages/Auth/Login.php b/app/Filament/Organizations/Pages/Auth/Login.php index ed344cef..dba52aca 100644 --- a/app/Filament/Organizations/Pages/Auth/Login.php +++ b/app/Filament/Organizations/Pages/Auth/Login.php @@ -6,7 +6,7 @@ use Filament\Pages\Auth\Login as BaseLogin; -class Login extends BaseLogin +class Login extends \Filament\Auth\Pages\Login { public function mount(): void { diff --git a/app/Filament/Organizations/Pages/Profile/UserPersonalInfo.php b/app/Filament/Organizations/Pages/Profile/UserPersonalInfo.php index ae4fae10..16af434a 100644 --- a/app/Filament/Organizations/Pages/Profile/UserPersonalInfo.php +++ b/app/Filament/Organizations/Pages/Profile/UserPersonalInfo.php @@ -4,37 +4,39 @@ namespace App\Filament\Organizations\Pages\Profile; +use Filament\Schemas\Schema; use Filament\Facades\Filament; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Jeffgreco13\FilamentBreezy\Livewire\PersonalInfo as BasePersonalInfo; +use Filament\Forms\Concerns\InteractsWithForms; +use Filament\Forms\Contracts\HasForms; +use Filament\Pages\SimplePage; +use Filament\Actions\Action; -class UserPersonalInfo extends BasePersonalInfo +class UserPersonalInfo extends SimplePage implements HasForms { - public array $only = [ - 'first_name', - 'last_name', - 'email', - ]; + use InteractsWithForms; + + protected string $view = 'filament.organizations.pages.profile.user-personal-info'; + + public ?array $data = []; public function mount(): void { - $this->user = Filament::getCurrentPanel()->auth()->user(); - - $this->form->fill($this->user->only($this->only)); + $user = Filament::getCurrentOrDefaultPanel()->auth()->user(); + $this->form->fill($user->only(['first_name', 'last_name', 'email'])); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form + return $schema ->columns(3) ->statePath('data') - ->model($this->user) - ->schema([ + ->model(Filament::getCurrentOrDefaultPanel()->auth()->user()) + ->components([ SpatieMediaLibraryFileUpload::make('avatar') - ->label(__('filament-breezy::default.fields.avatar')) + ->label(__('user.labels.avatar')) ->avatar() ->collection('avatar') ->conversion('large'), @@ -44,18 +46,37 @@ public function form(Form $form): Form ->columns(2) ->schema([ TextInput::make('first_name') - ->label(__('field.first_name')), + ->label(__('field.first_name')) + ->required(), TextInput::make('last_name') - ->label(__('field.last_name')), + ->label(__('field.last_name')) + ->required(), TextInput::make('email') - ->label(__('field.last_name')) - ->unique(ignoreRecord:true) + ->label(__('field.email')) + ->unique(ignoreRecord: true) ->required() ->email() ->columnSpanFull(), ]), ]); } + + protected function getFormActions(): array + { + return [ + Action::make('save') + ->label(__('general.action.save')) + ->submit('save'), + ]; + } + + public function save(): void + { + $user = Filament::getCurrentOrDefaultPanel()->auth()->user(); + $user->update($this->form->getState()); + + $this->notify('success', __('user.notifications.profile_updated')); + } } diff --git a/app/Filament/Organizations/Pages/ReportsPage.php b/app/Filament/Organizations/Pages/ReportsPage.php index 36e9c256..86ae3957 100644 --- a/app/Filament/Organizations/Pages/ReportsPage.php +++ b/app/Filament/Organizations/Pages/ReportsPage.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Pages; +use Filament\Forms\Contracts\HasForms; +use Filament\Schemas\Schema; use App\Actions\ExportReport; use App\Enums\ReportType; use App\Forms\Components\DatePicker; @@ -13,8 +15,8 @@ use Filament\Forms\Components\Select; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Section; use Filament\Infolists\Contracts\HasInfolists; use Filament\Infolists\Infolist; use Filament\Pages\Concerns\InteractsWithFormActions; @@ -22,16 +24,16 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Contracts\View\View; -class ReportsPage extends Page implements Forms\Contracts\HasForms, HasInfolists +class ReportsPage extends Page implements HasForms, HasInfolists { use InteractsWithForms; use InteractsWithFormActions; protected static ?int $navigationSort = 11; - protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static string $view = 'filament.organizations.pages.reports-page'; + protected string $view = 'filament.organizations.pages.reports-page'; public $report_type; @@ -68,16 +70,16 @@ public function submit(): void $this->form->getState(); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema($this->getFormSchema()); + return $schema + ->components($this->getFormSchema()); } protected function getFormSchema(): array { return [ - Forms\Components\Section::make() + Section::make() ->columns(12) ->schema([ Select::make('report_type') @@ -128,9 +130,9 @@ public function mount(): void $this->form->fill(); } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make(fn () => $this->report_type ? __('report.table_heading.' . $this->report_type) : null) ->hiddenLabel() ->headerActions([ diff --git a/app/Filament/Organizations/Pages/Tenancy/EditOrganizationProfile.php b/app/Filament/Organizations/Pages/Tenancy/EditOrganizationProfile.php index 063915f6..b9430472 100644 --- a/app/Filament/Organizations/Pages/Tenancy/EditOrganizationProfile.php +++ b/app/Filament/Organizations/Pages/Tenancy/EditOrganizationProfile.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Pages\Tenancy; +use Filament\Schemas\Schema; use App\Filament\Admin\Resources\OrganizationResource; use Filament\Forms\Form; use Filament\Pages\Tenancy\EditTenantProfile; @@ -17,8 +18,8 @@ public static function getLabel(): string return __('organization.profile'); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return OrganizationResource::form($form); + return OrganizationResource::form($schema); } } diff --git a/app/Filament/Organizations/Pages/ViewOrganizationTenant.php b/app/Filament/Organizations/Pages/ViewOrganizationTenant.php index 159991e8..782f2c5a 100644 --- a/app/Filament/Organizations/Pages/ViewOrganizationTenant.php +++ b/app/Filament/Organizations/Pages/ViewOrganizationTenant.php @@ -4,12 +4,13 @@ namespace App\Filament\Organizations\Pages; +use Filament\Schemas\Schema; use App\Filament\Admin\Resources\InstitutionResource\Pages\ViewInstitution; use App\Filament\Admin\Resources\InstitutionResource\RelationManagers\OrganizationsRelationManager; use App\Infolists\Components\Notice; use Filament\Facades\Filament; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; use Filament\Infolists\Concerns\InteractsWithInfolists; use Filament\Infolists\Contracts\HasInfolists; use Filament\Infolists\Infolist; @@ -20,9 +21,9 @@ class ViewOrganizationTenant extends Page implements HasInfolists { use InteractsWithInfolists; - protected static ?string $navigationIcon = 'heroicon-o-building-office'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-building-office'; - protected static string $view = 'filament.organizations.pages.view-organization-tenant'; + protected string $view = 'filament.organizations.pages.view-organization-tenant'; protected static ?int $navigationSort = 31; @@ -43,8 +44,8 @@ public function getTitle(): string|Htmlable public function infolist() { - return Infolist::make() - ->schema([ + return Schema::make() + ->components([ Section::make() ->maxWidth('3xl') ->schema([ diff --git a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource.php b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource.php index 796e7a63..23293be2 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource.php +++ b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource.php @@ -11,7 +11,6 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\Relation; class BeneficiaryHistoryResource extends Resource { @@ -19,32 +18,11 @@ class BeneficiaryHistoryResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static string $parentResource = BeneficiaryResource::class; + protected static bool $isScopedToTenant = false; - public static function getTenantOwnershipRelationship(Beneficiary|Model $record): Relation - { - $parent = Beneficiary::find(request('parent')); + public static ?string $parentResource = BeneficiaryResource::class; - return $parent->organization(); - } - public static function resolveRecordRouteBinding(int | string $key): ?Model - { - return app(static::getModel()) - ->resolveRouteBindingQuery(static::getEloquentQuery(), $key, static::getRecordRouteKeyName()) - ->when( - ! auth()->user()->hasAccessToAllCases() && ! auth()->user()->isNgoAdmin(), - fn (Builder $query) => $query->whereHasMorph( - 'subject', - Beneficiary::class, - fn (Builder $query) => $query->whereHas( - 'specialistsTeam', - fn (Builder $query) => $query->where('user_id', auth()->id()) - ) - ) - ) - ->first(); - } public static function getEloquentQuery(): Builder { diff --git a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ListBeneficiaryHistories.php b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ListBeneficiaryHistories.php index 107fa811..85ded9b7 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ListBeneficiaryHistories.php +++ b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ListBeneficiaryHistories.php @@ -91,9 +91,9 @@ public function table(Table $table): Table ->label(__('beneficiary.section.history.labels.subsection')) ->state(fn ($record) => self::getResource()::getSubsectionLabel($record)), ]) - ->actionsColumnLabel(__('beneficiary.section.history.labels.view_action')) - ->actions([ - ViewAction::make() + ->recordActionsColumnLabel(__('beneficiary.section.history.labels.view_action')) + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_details')) ->color('primary') ->url(fn (Activity $record) => self::getParentResource()::getUrl('beneficiary-histories.view', [ diff --git a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ViewBeneficiaryHistories.php b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ViewBeneficiaryHistories.php index 026ed269..69c64a44 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ViewBeneficiaryHistories.php +++ b/app/Filament/Organizations/Resources/BeneficiaryHistoryResource/Pages/ViewBeneficiaryHistories.php @@ -4,11 +4,12 @@ namespace App\Filament\Organizations\Resources\BeneficiaryHistoryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryHistoryResource; use App\Infolists\Components\HistoryChanges; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; use Illuminate\Contracts\Support\Htmlable; @@ -40,9 +41,9 @@ public function getTitle(): string|Htmlable return self::getResource()::getEventLabel($this->getRecord()); } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->columns() ->maxWidth('3xl') diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource.php index 17ba013b..40f39ac6 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource.php @@ -4,21 +4,13 @@ namespace App\Filament\Organizations\Resources; +use App\Filament\Organizations\Schemas\BeneficiaryInterventionResourceSchema; +use App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages\ListBeneficiaryInterventions; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages; -use App\Forms\Components\DatePicker; -use App\Forms\Components\Select; -use App\Models\Beneficiary; -use App\Models\BeneficiaryIntervention; use App\Models\InterventionService; -use App\Models\OrganizationServiceIntervention; -use App\Tables\Actions\EditAction; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Form; +use App\Models\BeneficiaryIntervention; use Filament\Resources\Resource; -use Filament\Tables; +use Filament\Schemas\Schema; use Filament\Tables\Table; class BeneficiaryInterventionResource extends Resource @@ -27,121 +19,27 @@ class BeneficiaryInterventionResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static string $parentResource = InterventionServiceResource::class; + public static ?string $parentResource = InterventionServiceResource::class; - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema([ - Section::make() - ->maxWidth('3xl') - ->columns() - ->schema(self::getSchema()), - ]); + return BeneficiaryInterventionResourceSchema::form($schema); } public static function getSchema(?Beneficiary $beneficiary = null, ?int $organizationServiceID = null): array { - return [ - Group::make() - ->schema([ - Select::make('organization_service_intervention_id') - ->label(__('intervention_plan.labels.intervention_type')) - ->relationship('organizationServiceIntervention', 'name') - ->options(function (?BeneficiaryIntervention $record) use ($organizationServiceID) { - $organizationServiceID = $record?->interventionService->organization_service_id ?? $organizationServiceID; - - return OrganizationServiceIntervention::with('serviceIntervention') - ->where('organization_service_id', $organizationServiceID) - ->active() - ->get() - ->filter( - fn (OrganizationServiceIntervention $organizationServiceIntervention) => $organizationServiceIntervention->serviceIntervention - ) - ->pluck('serviceIntervention.name', 'id'); - }) - ->required(), - - Select::make('specialist_id') - ->label(__('intervention_plan.labels.responsible_specialist')) - ->options(function (?BeneficiaryIntervention $record) use ($beneficiary) { - $beneficiary = $beneficiary ?? $record?->beneficiary; - - return $beneficiary - ->specialistsTeam - ->loadMissing([ - 'user:id,first_name,last_name', - 'role:id,name', - ]) - ->pluck('name_role', 'id'); - }), - ]), - - Grid::make() - ->schema([ - DatePicker::make('start_date_interval') - ->label(__('intervention_plan.labels.start_date_interval')), - - DatePicker::make('end_date_interval') - ->label(__('intervention_plan.labels.end_date_interval')), - ]), - - Section::make(__('intervention_plan.headings.intervention_indicators')) - ->collapsible(fn ($operation) => $operation != 'edit') - ->collapsed(fn ($operation) => $operation != 'edit') - ->compact() - ->schema([ - Textarea::make('objections') - ->label(__('intervention_plan.labels.objections')) - ->maxLength(7000) - ->columnSpanFull(), - - Textarea::make('expected_results') - ->label(__('intervention_plan.labels.expected_results')) - ->maxLength(1000) - ->columnSpanFull(), - - Textarea::make('procedure') - ->label(__('intervention_plan.labels.procedure')) - ->maxLength(1000) - ->columnSpanFull(), - - Textarea::make('indicators') - ->label(__('intervention_plan.labels.indicators')) - ->maxLength(1000) - ->columnSpanFull(), - - Textarea::make('achievement_degree') - ->label(__('intervention_plan.labels.achievement_degree')) - ->maxLength(1000) - ->columnSpanFull(), - ]), - ]; + return BeneficiaryInterventionResourceSchema::getFormComponents($beneficiary, $organizationServiceID); } public static function table(Table $table): Table { - return $table - ->columns([ - // - ]) - ->filters([ - // - ]) - ->actions([ - EditAction::make(), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]); + return BeneficiaryInterventionResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListBeneficiaryInterventions::route('/'), + 'index' => ListBeneficiaryInterventions::route('/'), // 'create' => Pages\CreateBeneficiaryIntervention::route('/create'), // 'edit' => Pages\EditBeneficiaryIntervention::route('/{record}/edit'), ]; diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/EditBeneficiaryIntervention.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/EditBeneficiaryIntervention.php index ce556b59..8b9a9693 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/EditBeneficiaryIntervention.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/EditBeneficiaryIntervention.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages; +use Filament\Actions\DeleteAction; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; @@ -49,7 +50,7 @@ protected function getHeaderActions(): array BackAction::make() ->url($this->getRedirectUrl()), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('intervention_plan.actions.delete_beneficiary_intervention')) ->outlined() ->modalHeading(__('intervention_plan.headings.delete_beneficiary_intervention_modal')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ListBeneficiaryInterventions.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ListBeneficiaryInterventions.php index fa50794a..383e4d45 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ListBeneficiaryInterventions.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ListBeneficiaryInterventions.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListBeneficiaryInterventions extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewBeneficiaryIntervention.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewBeneficiaryIntervention.php index 72c6b295..8573dd96 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewBeneficiaryIntervention.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewBeneficiaryIntervention.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasGroupPages; use App\Concerns\HasParentResource; @@ -12,8 +13,8 @@ use App\Filament\Organizations\Resources\InterventionServiceResource; use App\Infolists\Components\Actions\EditAction; use App\Services\Breadcrumb\InterventionPlanBreadcrumb; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -26,7 +27,7 @@ class ViewBeneficiaryIntervention extends ViewRecord protected static string $resource = BeneficiaryInterventionResource::class; - protected static string $view = 'filament.organizations.pages.view-beneficiary-interventions'; + protected string $view = 'filament.organizations.pages.view-beneficiary-interventions'; public function getBreadcrumbs(): array { @@ -52,7 +53,7 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { return $infolist ->schema([ diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewMeetings.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewMeetings.php index 720bebe1..e7b67f8d 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewMeetings.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewMeetings.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasGroupPages; use App\Concerns\HasParentResource; @@ -24,7 +25,7 @@ use Filament\Forms\Components\TimePicker; use Filament\Infolists\Components\Actions\Action; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -39,7 +40,7 @@ class ViewMeetings extends ViewRecord protected static string $resource = BeneficiaryInterventionResource::class; - protected static string $view = 'filament.organizations.pages.view-beneficiary-interventions'; + protected string $view = 'filament.organizations.pages.view-beneficiary-interventions'; public function getBreadcrumbs(): array { @@ -108,14 +109,14 @@ protected function getFormSchema(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { $this->getRecord()->loadMissing([ 'meetings.specialist.user:id,first_name,last_name', 'meetings.specialist.role:id,name', ]); - return $infolist->schema([ + return $schema->components([ Section::make() ->key('meetings') ->headerActions([ @@ -124,7 +125,7 @@ public function infolist(Infolist $infolist): Infolist ->model(InterventionMeeting::class) ->relationship(fn () => $this->record->meetings()) ->modalHeading(__('intervention_plan.actions.add_meeting')) - ->form($this->getFormSchema()) + ->schema($this->getFormSchema()) ->icon('heroicon-o-plus-circle') ->successRedirectUrl(fn () => InterventionServiceResource::getUrl('view_meetings', [ 'parent' => $this->getRecord()->interventionService, @@ -148,11 +149,11 @@ public function infolist(Infolist $infolist): Infolist ->action( EditAction::make() ->modalHeading(__('general.action.edit')) - ->form($this->getFormSchema()) + ->schema($this->getFormSchema()) ->fillForm(fn (InterventionMeeting $record) => $record->toArray()) ->extraModalFooterActions( fn () => [ - Action::make('delete') + \Filament\Actions\Action::make('delete') ->label(__('intervention_plan.actions.delete_meeting')) ->link() ->color('danger') diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewUnfoldedMeetings.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewUnfoldedMeetings.php index cf6c29f7..2f5ecd0e 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewUnfoldedMeetings.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Pages/ViewUnfoldedMeetings.php @@ -21,7 +21,7 @@ class ViewUnfoldedMeetings extends ViewRecord protected static string $resource = BeneficiaryInterventionResource::class; - protected static string $view = 'filament.organizations.pages.view-beneficiary-interventions'; + protected string $view = 'filament.organizations.pages.view-beneficiary-interventions'; public function getBreadcrumbs(): array { diff --git a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Widgets/UnfoldedWidget.php b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Widgets/UnfoldedWidget.php index 9648bc1d..06620207 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Widgets/UnfoldedWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryInterventionResource/Widgets/UnfoldedWidget.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Widgets; +use stdClass; use App\Filament\Organizations\Resources\InterventionServiceResource; use App\Models\BeneficiaryIntervention; use Filament\Tables\Actions\ViewAction; @@ -31,7 +32,7 @@ public function table(Table $table): Table ->columns([ TextColumn::make('meet_number') ->label(__('intervention_plan.labels.meet_number')) - ->state(static function (\stdClass $rowLoop) { + ->state(static function (stdClass $rowLoop) { return $rowLoop->iteration ?? null; }), TextColumn::make('status') @@ -67,8 +68,8 @@ public function table(Table $table): Table ->useTableQuery(), ]), ]) - ->actions([ - ViewAction::make() + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_observations')) ->url(fn () => InterventionServiceResource::getUrl('view_meetings', [ 'parent' => $this->record->interventionService, diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource.php b/app/Filament/Organizations/Resources/BeneficiaryResource.php index 2398df68..55f853e2 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource.php @@ -4,6 +4,37 @@ namespace App\Filament\Organizations\Resources; +use App\Filament\Organizations\Schemas\BeneficiaryResourceSchema; +use App\Filament\Organizations\Resources\BeneficiaryResource\RelationManagers\DocumentsRelationManager; +use Filament\Actions\ViewAction; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ListBeneficiaries; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CreateBeneficiary; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ViewBeneficiary; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ViewBeneficiaryIdentity; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditBeneficiaryIdentity; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditChildrenIdentity; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ViewBeneficiaryPersonalInformation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditBeneficiaryPersonalInformation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditAggressor; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditAntecedents; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\EditFlowPresentation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\ViewInitialEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\CreateInitialEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\EditEvaluationDetails; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\EditViolence; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\EditRiskFactors; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\EditRequestedServices; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation\EditBeneficiarySituation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\ViewDetailedEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\CreateDetailedEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\EditDetailedEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\EditBeneficiaryPartner; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\EditMultidisciplinaryEvaluation; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation\EditDetailedEvaluationResult; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile\CreateCloseFile; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile\ViewCloseFile; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile\EditCloseFileDetails; +use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile\EditCloseFileGeneralDetails; use App\Enums\CaseStatus; use App\Filament\Organizations\Resources\BeneficiaryHistoryResource\Pages\ListBeneficiaryHistories; use App\Filament\Organizations\Resources\BeneficiaryHistoryResource\Pages\ViewBeneficiaryHistories; @@ -12,8 +43,6 @@ use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ListSpecialists; -use App\Filament\Organizations\Resources\DocumentResource\Pages\ListDocuments; -use App\Filament\Organizations\Resources\DocumentResource\Pages\ViewDocument; use App\Filament\Organizations\Resources\InterventionPlanResource\Pages\CreateInterventionPlan; use App\Filament\Organizations\Resources\InterventionPlanResource\Pages\ViewInterventionPlan; use App\Filament\Organizations\Resources\MonitoringResource\Pages as MonitoringResourcePages; @@ -32,7 +61,7 @@ class BeneficiaryResource extends Resource { protected static ?string $model = Beneficiary::class; - protected static ?string $navigationIcon = 'heroicon-o-folder'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-folder'; protected static ?string $slug = 'cases'; @@ -70,133 +99,49 @@ public static function getGlobalSearchResultTitle(Model $record): string public static function table(Table $table): Table { - return $table - ->modifyQueryUsing(function (Builder $query) { - return $query - ->with([ - 'managerTeam', - 'lastMonitoring', - // used for permissions - 'specialistsMembers', - ]) - ->whereUserHasAccess(); - }) - ->columns([ - TextColumn::make('id') - ->label(__('field.case_id')) - ->sortable() - ->searchable(true, fn (Builder $query, $search) => $query->where('beneficiaries.id', 'LIKE', '%' . $search . '%')), - - TextColumn::make('full_name') - ->label(__('field.beneficiary')) - ->description(fn ($record) => $record->initial_id ? __('beneficiary.labels.reactivated') : '') - ->sortable() - ->searchable(true, fn (Builder $query, $search) => $query->where('beneficiaries.full_name', 'LIKE', '%' . $search . '%')), - - TextColumn::make('created_at') - ->label(__('field.open_at')) - ->date() - ->toggleable() - ->sortable(), - - TextColumn::make('lastMonitoring.date') - ->label(__('field.last_evaluated_at')) - ->date() - ->toggleable(), - - TextColumn::make('managerTeam.user.full_name') - ->label(__('beneficiary.labels.case_manager')) - ->toggleable() - ->formatStateUsing( - fn ($state) => collect(explode(',', $state)) - ->map(fn ($item) => trim($item)) - ->unique() - ->join(', ') - ), - - TextColumn::make('status') - ->label(__('field.status')) - ->badge(), - ]) - ->actions([ - Tables\Actions\ViewAction::make() - ->label(__('general.action.view_details')), - ]) - ->filters([ - SelectFilter::make('status') - ->label(__('field.status')) - ->options(CaseStatus::options()) - ->modifyQueryUsing(fn (Builder $query, $state) => $state['value'] ? $query->where('beneficiaries.status', $state) : $query), - - SelectFilter::make('case_manager') - ->label(__('beneficiary.labels.case_manager')) - ->searchable() - ->preload() - ->relationship('managerTeam.user', 'full_name'), - - DateFilter::make('created_at') - ->label(__('field.open_at')) - ->attribute('beneficiaries.created_at'), - - DateFilter::make('monitorings.date') - ->label(__('field.last_evaluated_at')) - ->modifyQueryUsing( - fn (Builder $query, array $state) => $query - ->when(data_get($state, 'date_from'), function (Builder $query, string $date) { - $query->whereHas('lastMonitoring', fn (Builder $query) => $query->whereDate('date', '>=', $date)); - }) - ->when(data_get($state, 'date_until'), function (Builder $query, string $date) { - $query->whereHas('lastMonitoring', fn (Builder $query) => $query->whereDate('date', '<=', $date)); - }) - ), - ]) - ->paginationPageOptions([10, 20, 40, 60, 80, 100]) - ->defaultPaginationPageOption(20) - ->defaultSort('id', 'desc'); + return BeneficiaryResourceSchema::table($table); } public static function getRelations(): array { return [ - // + 'documents' => DocumentsRelationManager::class, ]; } public static function getPages(): array { return [ - 'index' => Pages\ListBeneficiaries::route('/'), - 'create' => Pages\CreateBeneficiary::route('/create/{parent?}'), - 'view' => Pages\ViewBeneficiary::route('/{record}'), - - 'view_identity' => Pages\ViewBeneficiaryIdentity::route('/{record}/identity'), - 'edit_identity' => Pages\EditBeneficiaryIdentity::route('/{record}/identity/edit'), - 'edit_children' => Pages\EditChildrenIdentity::route('{record}/children/edit'), - 'view_personal_information' => Pages\ViewBeneficiaryPersonalInformation::route('/{record}/personal'), - 'edit_personal_information' => Pages\EditBeneficiaryPersonalInformation::route('/{record}/personal/edit'), - 'edit_aggressor' => Pages\EditAggressor::route('/{record}/aggressor/edit'), - 'edit_antecedents' => Pages\EditAntecedents::route('{record}/antecedents/edit'), - 'edit_flow_presentation' => Pages\EditFlowPresentation::route('{record}/flowPresentation/edit'), - - 'view_initial_evaluation' => InitialEvaluation\ViewInitialEvaluation::route('/{record}/initialEvaluation'), - 'create_initial_evaluation' => InitialEvaluation\CreateInitialEvaluation::route('/{record}/initialEvaluation/create'), - 'edit_initial_evaluation_details' => InitialEvaluation\EditEvaluationDetails::route('/{record}/initialEvaluation/details/edit'), - 'edit_initial_evaluation_violence' => InitialEvaluation\EditViolence::route('/{record}/initialEvaluation/violence/edit'), - 'edit_initial_evaluation_risk_factors' => InitialEvaluation\EditRiskFactors::route('/{record}/initialEvaluation/riskFactors/edit'), - 'edit_initial_evaluation_requested_services' => InitialEvaluation\EditRequestedServices::route('/{record}/initialEvaluation/requestedServices/edit'), - 'edit_initial_evaluation_beneficiary_situation' => InitialEvaluation\EditBeneficiarySituation::route('/{record}/initialEvaluation/beneficiarySituation/edit'), - - 'view_detailed_evaluation' => DetailedEvaluation\ViewDetailedEvaluation::route('/{record}/detailedEvaluation'), - 'create_detailed_evaluation' => DetailedEvaluation\CreateDetailedEvaluation::route('/{record}/detailedEvaluation/create'), - 'edit_detailed_evaluation' => DetailedEvaluation\EditDetailedEvaluation::route('/{record}/detailedEvaluation/edit'), - 'edit_beneficiary_partner' => DetailedEvaluation\EditBeneficiaryPartner::route('/{record}/beneficiaryPartner/edit'), - 'edit_multidisciplinary_evaluation' => DetailedEvaluation\EditMultidisciplinaryEvaluation::route('/{record}/multidisciplinaryEvaluation/edit'), - 'edit_detailed_evaluation_result' => DetailedEvaluation\EditDetailedEvaluationResult::route('/{record}/detailedEvaluationResult/edit'), + 'index' => ListBeneficiaries::route('/'), + 'create' => CreateBeneficiary::route('/create/{parent?}'), + 'view' => ViewBeneficiary::route('/{record}'), + + 'view_identity' => ViewBeneficiaryIdentity::route('/{record}/identity'), + 'edit_identity' => EditBeneficiaryIdentity::route('/{record}/identity/edit'), + 'edit_children' => EditChildrenIdentity::route('{record}/children/edit'), + 'view_personal_information' => ViewBeneficiaryPersonalInformation::route('/{record}/personal'), + 'edit_personal_information' => EditBeneficiaryPersonalInformation::route('/{record}/personal/edit'), + 'edit_aggressor' => EditAggressor::route('/{record}/aggressor/edit'), + 'edit_antecedents' => EditAntecedents::route('{record}/antecedents/edit'), + 'edit_flow_presentation' => EditFlowPresentation::route('{record}/flowPresentation/edit'), + + 'view_initial_evaluation' => ViewInitialEvaluation::route('/{record}/initialEvaluation'), + 'create_initial_evaluation' => CreateInitialEvaluation::route('/{record}/initialEvaluation/create'), + 'edit_initial_evaluation_details' => EditEvaluationDetails::route('/{record}/initialEvaluation/details/edit'), + 'edit_initial_evaluation_violence' => EditViolence::route('/{record}/initialEvaluation/violence/edit'), + 'edit_initial_evaluation_risk_factors' => EditRiskFactors::route('/{record}/initialEvaluation/riskFactors/edit'), + 'edit_initial_evaluation_requested_services' => EditRequestedServices::route('/{record}/initialEvaluation/requestedServices/edit'), + 'edit_initial_evaluation_beneficiary_situation' => EditBeneficiarySituation::route('/{record}/initialEvaluation/beneficiarySituation/edit'), + + 'view_detailed_evaluation' => ViewDetailedEvaluation::route('/{record}/detailedEvaluation'), + 'create_detailed_evaluation' => CreateDetailedEvaluation::route('/{record}/detailedEvaluation/create'), + 'edit_detailed_evaluation' => EditDetailedEvaluation::route('/{record}/detailedEvaluation/edit'), + 'edit_beneficiary_partner' => EditBeneficiaryPartner::route('/{record}/beneficiaryPartner/edit'), + 'edit_multidisciplinary_evaluation' => EditMultidisciplinaryEvaluation::route('/{record}/multidisciplinaryEvaluation/edit'), + 'edit_detailed_evaluation_result' => EditDetailedEvaluationResult::route('/{record}/detailedEvaluationResult/edit'), 'view_specialists' => ListSpecialists::route('/{record}/specialists'), - 'documents.index' => ListDocuments::route('/{parent}/documents'), - 'documents.view' => ViewDocument::route('/{parent}/documents/{record}'), 'monitorings.create' => MonitoringResourcePages\CreateMonitoring::route('/{parent}/monitoring/create/{copyLastFile?}'), 'monitorings.index' => MonitoringResourcePages\ListMonitoring::route('/{parent}/monitoring'), @@ -208,10 +153,10 @@ public static function getPages(): array 'beneficiary-histories.index' => ListBeneficiaryHistories::route('{parent}/history'), 'beneficiary-histories.view' => ViewBeneficiaryHistories::route('{parent}/history/{record}'), - 'create_close_file' => CloseFile\CreateCloseFile::route('/{record}/createCloseFile'), - 'view_close_file' => CloseFile\ViewCloseFile::route('/{record}/closeFile'), - 'edit_close_file_details' => CloseFile\EditCloseFileDetails::route('{record}/closeFile/editDetails'), - 'edit_close_file_general_details' => CloseFile\EditCloseFileGeneralDetails::route('{record}/closeFile/editGeneralDetails'), + 'create_close_file' => CreateCloseFile::route('/{record}/createCloseFile'), + 'view_close_file' => ViewCloseFile::route('/{record}/closeFile'), + 'edit_close_file_details' => EditCloseFileDetails::route('{record}/closeFile/editDetails'), + 'edit_close_file_general_details' => EditCloseFileGeneralDetails::route('{record}/closeFile/editGeneralDetails'), 'create_intervention_plan' => CreateInterventionPlan::route('/{parent}/createInterventionPlan'), 'view_intervention_plan' => ViewInterventionPlan::route('/{parent}/interventionPlan/{record}'), diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Actions/ViewDetailsAction.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Actions/ViewDetailsAction.php index 76d819a3..3d2e0e1b 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Actions/ViewDetailsAction.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Actions/ViewDetailsAction.php @@ -6,7 +6,7 @@ use Filament\Infolists\Components\Actions\Action; -class ViewDetailsAction extends Action +class ViewDetailsAction extends \Filament\Actions\Action { protected function setUp(): void { diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/CreateCloseFile.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/CreateCloseFile.php index b856a993..8b016702 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/CreateCloseFile.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/CreateCloseFile.php @@ -11,9 +11,9 @@ use App\Models\Specialist; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Actions\Action; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Wizard\Step; -use Filament\Forms\Set; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Wizard\Step; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileDetails.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileDetails.php index 2fe832fc..29a2e125 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileDetails.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileDetails.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToCloseFile; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -12,7 +13,7 @@ use App\Models\Beneficiary; use App\Models\CloseFile; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; @@ -45,18 +46,18 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.close_file.headings.file_details')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') ->columns() ->relationship('closeFile') - ->schema($this->getSchema()), + ->schema($this->getFormSchema()), ]); } - public static function getSchema(?Beneficiary $recordParam = null): array + protected function getFormSchema(?Beneficiary $recordParam = null): array { return [ DatePicker::make('date') diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileGeneralDetails.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileGeneralDetails.php index 70df067c..64ee9df5 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileGeneralDetails.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/EditCloseFileGeneralDetails.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToCloseFile; use App\Enums\AdmittanceReason; @@ -13,10 +14,10 @@ use Filament\Forms\Components\CheckboxList; use Filament\Forms\Components\Radio; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -47,17 +48,17 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.close_file.headings.general_details')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') ->relationship('closeFile') - ->schema($this->getSchema()), + ->schema($this->getFormSchema()), ]); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ CheckboxList::make('admittance_reason') diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/ViewCloseFile.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/ViewCloseFile.php index 09e96b87..71dfa914 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/ViewCloseFile.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CloseFile/ViewCloseFile.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\CloseFile; +use Filament\Schemas\Schema; +use Filament\Schemas\Components\Tabs\Tab; use App\Actions\BackAction; use App\Enums\CloseMethod; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -14,8 +16,8 @@ use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Actions\DeleteAction; use Filament\Infolists\Components\Actions\Action; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -58,14 +60,14 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Tabs::make() ->columnSpanFull() ->persistTabInQueryString() ->tabs([ - Tabs\Tab::make(__('beneficiary.section.close_file.headings.file_details')) + Tab::make(__('beneficiary.section.close_file.headings.file_details')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.section.close_file.headings.file_details_simple')) @@ -89,7 +91,7 @@ public function infolist(Infolist $infolist): Infolist ]), ]), - Tabs\Tab::make(__('beneficiary.section.identity.tab.beneficiary')) + Tab::make(__('beneficiary.section.identity.tab.beneficiary')) ->maxWidth('3xl') ->schema([ Section::make() @@ -100,7 +102,7 @@ public function infolist(Infolist $infolist): Infolist ->state(__('beneficiary.section.identity.heading_description')) ->color('primary') ->action( - Action::make('view') + \Filament\Actions\Action::make('view') ->label(__('beneficiary.section.identity.title')) ->url(self::$resource::getUrl('view_identity', ['record' => $this->getRecord()])) ->link(), @@ -117,7 +119,7 @@ public function infolist(Infolist $infolist): Infolist ]), ]), - Tabs\Tab::make(__('beneficiary.section.close_file.headings.general_details')) + Tab::make(__('beneficiary.section.close_file.headings.general_details')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.section.close_file.headings.general_details')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CreateBeneficiary.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CreateBeneficiary.php index bab13ac3..87abaaba 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CreateBeneficiary.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/CreateBeneficiary.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventMultipleSubmit; use App\Concerns\PreventSubmitFormOnEnter; use App\Enums\AddressType; @@ -15,19 +16,19 @@ use App\Rules\ValidCNP; use Carbon\Carbon; use Filament\Facades\Filament; -use Filament\Forms\Components\Actions\Action; +use Filament\Actions\Action; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Wizard; -use Filament\Forms\Components\Wizard\Step; +use Filament\Schemas\Components\Wizard; +use Filament\Schemas\Components\Wizard\Step; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\CreateRecord; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Illuminate\Contracts\Support\Htmlable; @@ -83,10 +84,10 @@ protected function setParentBeneficiary(): void $this->parentBeneficiary = $parentBeneficiaryID ? Beneficiary::find($parentBeneficiaryID) : null; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return parent::form($form) - ->schema([ + return parent::form($schema) + ->components([ Wizard::make($this->getSteps()) ->extraAlpineAttributes([ '@copy_beneficiary_data.window' => "step='beneficiary'", @@ -208,7 +209,7 @@ function (Get $get, Set $set) { ])); }) ->registerActions([ - Action::make('view_beneficiary') + \Filament\Actions\Action::make('view_beneficiary') ->label(__('beneficiary.action.view_case_details')) ->link() ->url( @@ -224,7 +225,7 @@ function (Get $get, Set $set) { ->first() ), - Action::make('view_beneficiary_from_another_tenant') + \Filament\Actions\Action::make('view_beneficiary_from_another_tenant') ->label(__('beneficiary.action.copy_beneficiary_data')) ->link() ->modalHeading(__('beneficiary.headings.modal_create_beneficiary_from_anther_tenant')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/CreateDetailedEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/CreateDetailedEvaluation.php index 76798e21..49d47b4d 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/CreateDetailedEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/CreateDetailedEvaluation.php @@ -10,7 +10,7 @@ use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Models\BeneficiaryPartner; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Wizard\Step; +use Filament\Schemas\Components\Wizard\Step; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditBeneficiaryPartner.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditBeneficiaryPartner.php index 80241d0b..f49460f5 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditBeneficiaryPartner.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditBeneficiaryPartner.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToDetailedEvaluation; use App\Enums\AddressType; @@ -13,12 +14,12 @@ use App\Forms\Components\Select; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -46,12 +47,12 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.partner.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components($this->getFormSchema()); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Section::make(__('beneficiary.section.detailed_evaluation.heading.partner')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluation.php index fe810c3b..85446419 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluation.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToDetailedEvaluation; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -13,7 +14,7 @@ use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Awcodes\TableRepeater\Header; use Filament\Facades\Filament; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; @@ -32,9 +33,9 @@ public function getTitle(): string|Htmlable return __('beneficiary.page.edit_evaluation_details.title'); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components($this->getFormSchema()); } public function getBreadcrumbs(): array @@ -48,7 +49,7 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.detailed_evaluation.label')); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Section::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluationResult.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluationResult.php index 27f6e6a4..5e8d609c 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluationResult.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditDetailedEvaluationResult.php @@ -4,15 +4,16 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToDetailedEvaluation; use App\Enums\RecommendationService; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; @@ -42,12 +43,12 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.results.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components($this->getFormSchema()); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Group::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditMultidisciplinaryEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditMultidisciplinaryEvaluation.php index c80b3fda..39ef6e1d 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditMultidisciplinaryEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/EditMultidisciplinaryEvaluation.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToDetailedEvaluation; use App\Enums\Applicant; @@ -11,13 +12,13 @@ use App\Forms\Components\Repeater; use App\Forms\Components\Select; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -41,9 +42,9 @@ public function getBreadcrumbs(): array ->getBreadcrumbs('view_detailed_evaluation'); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components($this->getFormSchema()); } protected function getTabSlug(): string @@ -51,7 +52,7 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.multidisciplinary_evaluation.label')); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Section::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/ViewDetailedEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/ViewDetailedEvaluation.php index 5ae2afbe..099ccb48 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/ViewDetailedEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/DetailedEvaluation/ViewDetailedEvaluation.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\DetailedEvaluation; +use Filament\Schemas\Schema; +use Filament\Schemas\Components\Tabs\Tab; use App\Actions\BackAction; use App\Enums\AddressType; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -13,10 +15,10 @@ use App\Infolists\Components\Location; use App\Infolists\Components\TableEntry; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Infolists\Components\Group; +use Filament\Schemas\Components\Group; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -45,15 +47,15 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist + return $schema ->columns(1) ->schema([ Tabs::make() ->persistTabInQueryString() ->tabs([ - Tabs\Tab::make(__('beneficiary.wizard.detailed_evaluation.label')) + Tab::make(__('beneficiary.wizard.detailed_evaluation.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.detailed_evaluation.label')) @@ -67,15 +69,15 @@ public function infolist(Infolist $infolist): Infolist ->schema($this->getDetailedEvaluationSchema()), ]), - Tabs\Tab::make(__('beneficiary.section.identity.tab.beneficiary')) + Tab::make(__('beneficiary.section.identity.tab.beneficiary')) ->maxWidth('3xl') ->schema(ViewBeneficiaryIdentity::identitySchemaForOtherPage($this->record)), - Tabs\Tab::make(__('beneficiary.section.identity.tab.children')) + Tab::make(__('beneficiary.section.identity.tab.children')) ->maxWidth('3xl') ->schema(ViewBeneficiaryIdentity::childrenSchemaForOtherPage($this->record)), - Tabs\Tab::make(__('beneficiary.wizard.partner.label')) + Tab::make(__('beneficiary.wizard.partner.label')) ->maxWidth('3xl') ->schema([ Group::make() @@ -94,7 +96,7 @@ public function infolist(Infolist $infolist): Infolist ]), ]), - Tabs\Tab::make(__('beneficiary.wizard.multidisciplinary_evaluation.label')) + Tab::make(__('beneficiary.wizard.multidisciplinary_evaluation.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.multidisciplinary_evaluation.label')) @@ -108,7 +110,7 @@ public function infolist(Infolist $infolist): Infolist ->schema($this->getMultidisciplinarySchema()), ]), - Tabs\Tab::make(__('beneficiary.wizard.results.label')) + Tab::make(__('beneficiary.wizard.results.label')) ->maxWidth('3xl') ->schema([ Group::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAggressor.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAggressor.php index ef82522e..eb7f519a 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAggressor.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAggressor.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToPersonalInformation; use App\Enums\AggressorLegalHistory; @@ -22,14 +23,14 @@ use App\Forms\Components\Select; use App\Rules\MultipleIn; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Actions\Action; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Section; +use Filament\Actions\Action; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -57,10 +58,10 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.personal_information.section.aggressor')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema(static::getPersonalInformationFormSchema()); + return $schema + ->components(static::getPersonalInformationFormSchema()); } public static function getPersonalInformationFormSchema(): array @@ -81,14 +82,14 @@ public static function aggressorSection(): array ->columns() ->minItems(1) ->addAction( - fn (Action $action): Action => $action + fn (\Filament\Actions\Action $action): \Filament\Actions\Action => $action ->label(__('beneficiary.section.personal_information.actions.add_aggressor')) ->link() ->color('primary') ->extraAttributes(['class' => 'pull-left']) ) ->deleteAction( - fn (Action $action) => $action + fn (\Filament\Actions\Action $action) => $action ->label(__('beneficiary.section.personal_information.actions.delete_aggressor')) ->icon(null) ->link() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAntecedents.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAntecedents.php index 94d3170d..6ff0e30e 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAntecedents.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditAntecedents.php @@ -4,18 +4,19 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToPersonalInformation; use App\Enums\Ternary; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Forms\Components\Select; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -43,10 +44,10 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.personal_information.section.antecedents')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema(static::getPersonalInformationFormSchema()); + return $schema + ->components(static::getPersonalInformationFormSchema()); } public static function getPersonalInformationFormSchema(): array diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryIdentity.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryIdentity.php index 3fec90e0..31a81ad8 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryIdentity.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryIdentity.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use alcea\cnp\Cnp; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToIdentity; @@ -22,14 +23,14 @@ use App\Rules\ValidCNP; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Query\Builder; @@ -59,11 +60,11 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.identity.tab.beneficiary')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form + return $schema ->columns(1) - ->schema([ + ->components([ Section::make() ->schema(static::getBeneficiaryIdentityFormSchema()), ]); diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryPersonalInformation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryPersonalInformation.php index c3b867bb..08bf26ce 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryPersonalInformation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditBeneficiaryPersonalInformation.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToPersonalInformation; use App\Enums\DisabilityDegree; @@ -19,12 +20,12 @@ use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Forms\Components\Select; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -55,10 +56,10 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.personal_information.section.beneficiary')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema(static::getPersonalInformationFormSchema()); + return $schema + ->components(static::getPersonalInformationFormSchema()); } public static function getPersonalInformationFormSchema(): array diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditChildrenIdentity.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditChildrenIdentity.php index 3039f454..6af6b00e 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditChildrenIdentity.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditChildrenIdentity.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToIdentity; use App\Enums\GenderShortValues; @@ -15,14 +16,14 @@ use Awcodes\TableRepeater\Header; use Carbon\Carbon; use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -50,11 +51,11 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.identity.tab.children')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form + return $schema ->columns(1) - ->schema([ + ->components([ Section::make() ->schema(static::getChildrenIdentityFormSchema()), ]); @@ -145,45 +146,18 @@ public static function getChildrenIdentityFormSchema(): array ]), ]), - TableRepeater::make('children') - ->reorderable(false) + Repeater::make('children') ->relationship('children') ->columnSpanFull() - ->extraAttributes(['class' => 'm']) - ->hiddenLabel() ->addActionLabel(__('beneficiary.action.add_child')) ->disabled(fn (Get $get) => $get('doesnt_have_children')) ->hidden(fn (Get $get) => $get('doesnt_have_children')) - ->emptyLabel(false) ->defaultItems(fn (Get $get) => $get('doesnt_have_children') ? 0 : 1) - ->headers([ - Header::make('name') - ->label(__('field.child_name')), - - Header::make('birthdate') - ->label(__('field.birthdate')), - - Header::make('age') - ->label(__('field.age')) - ->width('60px'), - - Header::make('gender') - ->label(__('field.gender')) - ->width('120px'), - - Header::make('current_address') - ->label(__('field.current_address')), - - Header::make('status') - ->label(__('field.child_status')), - - Header::make('workspace') - ->label(__('field.workspace')), - ]) ->schema([ TextInput::make('name') ->label(__('field.child_name')) - ->maxLength(70), + ->maxLength(70) + ->required(), DatePicker::make('birthdate') ->label(__('field.birthdate')) @@ -203,7 +177,8 @@ function () use ($state) { TextInput::make('age') ->label(__('field.age')) - ->disabled(), + ->disabled() + ->dehydrated(false), Select::make('gender') ->label(__('field.gender')) @@ -221,7 +196,10 @@ function () use ($state) { TextInput::make('workspace') ->label(__('field.workspace')) ->maxLength(70), - ]), + ]) + ->columns(7) + ->itemLabel(fn (array $state): ?string => $state['name'] ?? null) + ->collapsible(), Textarea::make('children_notes') ->label(__('field.children_notes')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditFlowPresentation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditFlowPresentation.php index ad0e4edd..49998ae6 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditFlowPresentation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/EditFlowPresentation.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToPersonalInformation; use App\Enums\ActLocation; @@ -15,11 +16,11 @@ use App\Forms\Components\Select; use App\Rules\MultipleIn; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -47,10 +48,10 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.section.personal_information.section.flow')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema(static::getPersonalInformationFormSchema()); + return $schema + ->components(static::getPersonalInformationFormSchema()); } public static function getPersonalInformationFormSchema(): array diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/CreateInitialEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/CreateInitialEvaluation.php index 6a92c506..fb18680d 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/CreateInitialEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/CreateInitialEvaluation.php @@ -9,7 +9,7 @@ use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Wizard\Step; +use Filament\Schemas\Components\Wizard\Step; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditBeneficiarySituation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditBeneficiarySituation.php index 2f75f39a..cf3899ab 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditBeneficiarySituation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditBeneficiarySituation.php @@ -4,16 +4,12 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use App\Filament\Organizations\Schemas\BeneficiaryResource\InitialEvaluationSchema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToInitialEvaluation; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Infolists\Components\Group as InfolistGroup; -use Filament\Infolists\Components\TextEntry; +use Filament\Schemas\Schema; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -41,44 +37,13 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.beneficiary_situation.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); - } - - public static function getSchema(): array - { - return [ - Section::make() - ->relationship('beneficiarySituation') - ->maxWidth('3xl') - ->schema([ - TextInput::make('moment_of_evaluation') - ->label(__('beneficiary.section.initial_evaluation.labels.moment_of_evaluation')) - ->placeholder(__('beneficiary.placeholder.moment_of_evaluation')) - ->maxLength(100), - - RichEditor::make('description_of_situation') - ->label(__('beneficiary.section.initial_evaluation.labels.description_of_situation')) - ->placeholder(__('beneficiary.placeholder.description_of_situation')) - ->maxLength(5000), - ]), - ]; + return $schema->components(InitialEvaluationSchema::getBeneficiarySituationFormComponents()); } public static function getInfoListSchema(): array { - return [ - InfolistGroup::make() - ->relationship('beneficiarySituation') - ->schema([ - TextEntry::make('moment_of_evaluation') - ->label(__('beneficiary.section.initial_evaluation.labels.moment_of_evaluation')), - - TextEntry::make('description_of_situation') - ->label(__('beneficiary.section.initial_evaluation.labels.description_of_situation')) - ->html(), - ]), - ]; + return InitialEvaluationSchema::getBeneficiarySituationInfolistComponents(); } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditEvaluationDetails.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditEvaluationDetails.php index f5e1efdb..ec7c4d55 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditEvaluationDetails.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditEvaluationDetails.php @@ -4,20 +4,12 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use App\Filament\Organizations\Schemas\BeneficiaryResource\InitialEvaluationSchema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToInitialEvaluation; use App\Filament\Organizations\Resources\BeneficiaryResource; -use App\Forms\Components\DatePicker; -use App\Forms\Components\Select; -use App\Infolists\Components\DateEntry; -use App\Models\User; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Infolists\Components\Group; -use Filament\Infolists\Components\TextEntry; +use Filament\Schemas\Schema; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -34,9 +26,9 @@ public function getTitle(): string|Htmlable return __('beneficiary.page.edit_evaluation_details.title'); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); + return $schema->components(InitialEvaluationSchema::getEvaluationDetailsFormComponents()); } public function getBreadcrumbs(): array @@ -50,63 +42,8 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.details.label')); } - public static function getSchema(): array - { - return [ - Section::make() - ->relationship('evaluateDetails') - ->maxWidth('3xl') - ->columns() - ->schema([ - DatePicker::make('registered_date') - ->label(__('beneficiary.section.initial_evaluation.labels.registered_date')) - ->required(), - - TextInput::make('file_number') - ->label(__('beneficiary.section.initial_evaluation.labels.file_number')) - ->placeholder(__('beneficiary.placeholder.file_number')) - ->maxLength(50), - - Select::make('specialist_id') - ->label(__('beneficiary.section.initial_evaluation.labels.specialist')) - ->placeholder(__('beneficiary.placeholder.specialist')) - ->required() - ->default(auth()->user()->id) - ->options(fn ($record) => User::getTenantOrganizationUsers()), - - Textarea::make('method_of_identifying_the_service') - ->label(__('beneficiary.section.initial_evaluation.labels.method_of_identifying_the_service')) - ->placeholder(__('beneficiary.placeholder.method_of_identifying_the_service')) - ->columnSpanFull() - ->maxLength(2000), - ]), - - ]; - } - public static function getInfoListSchema(): array { - return [ - Group::make() - ->columns() - ->relationship('evaluateDetails') - ->schema([ - DateEntry::make('registered_date') - ->label(__('beneficiary.section.initial_evaluation.labels.registered_date')), - - TextEntry::make('file_number') - ->label(__('beneficiary.section.initial_evaluation.labels.file_number')) - ->placeholder(__('beneficiary.placeholder.file_number')), - - TextEntry::make('specialist.full_name') - ->label(__('beneficiary.section.initial_evaluation.labels.specialist')) - ->placeholder(__('beneficiary.placeholder.specialist')), - - TextEntry::make('method_of_identifying_the_service') - ->label(__('beneficiary.section.initial_evaluation.labels.method_of_identifying_the_service')) - ->placeholder(__('beneficiary.placeholder.method_of_identifying_the_service')) - ->columnSpanFull(), - ]), - ]; + return InitialEvaluationSchema::getEvaluationDetailsInfolistComponents(); } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRequestedServices.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRequestedServices.php index 352badb4..3e02b761 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRequestedServices.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRequestedServices.php @@ -4,16 +4,14 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use App\Filament\Organizations\Schemas\BeneficiaryResource\InitialEvaluationSchema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToInitialEvaluation; -use App\Enums\RecommendationService; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Form; +use Filament\Schemas\Schema; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -41,14 +39,14 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.requested_services.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema( - self::getSchema() + return $schema->components( + $this->getFormSchema() ); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Group::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRiskFactors.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRiskFactors.php index fc61e43b..bce83939 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRiskFactors.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditRiskFactors.php @@ -4,32 +4,21 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use App\Filament\Organizations\Schemas\BeneficiaryResource\InitialEvaluationSchema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToInitialEvaluation; use App\Enums\AggravatingFactorsSchema; -use App\Enums\Helps; use App\Enums\RiskFactorsSchema; -use App\Enums\Ternary; use App\Enums\VictimPerceptionOfTheRiskSchema; use App\Enums\ViolenceHistorySchema; use App\Enums\ViolencesTypesSchema; use App\Filament\Organizations\Resources\BeneficiaryResource; -use App\Forms\Components\Select; use App\Infolists\Components\EnumEntry; use App\Models\Beneficiary; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Radio; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; -use Filament\Infolists\Components\Group as InfolistGroup; -use Filament\Infolists\Components\Section as InfolistSection; -use Filament\Infolists\Components\TextEntry; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Schema; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -57,152 +46,33 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.risk_factors.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); - } - - public static function getSchema(): array - { - return [ - Group::make() - ->relationship('riskFactors') - ->schema([ - Section::make(__('beneficiary.section.initial_evaluation.heading.violence_history')) - ->schema(self::getViolenceHistorySchema()), - Section::make(__('beneficiary.section.initial_evaluation.heading.violences_types')) - ->schema(self::getViolencesTypesSchema()), - Section::make(__('beneficiary.section.initial_evaluation.heading.risk_factors')) - ->schema(self::getRiskFactorsSchema()), - Section::make(__('beneficiary.section.initial_evaluation.heading.victim_perception_of_the_risk')) - ->schema(self::getVictimPerceptionOfTheRiskSchema()), - Section::make(__('beneficiary.section.initial_evaluation.heading.aggravating_factors')) - ->schema(self::getAggravatingFactorsSchema()), - Section::make(__('beneficiary.section.initial_evaluation.heading.social_support')) - ->columns() - ->schema(self::getSocialSupportSchema()), - ]), - ]; - } - - public static function getViolenceHistorySchema(): array - { - $enumOptions = ViolenceHistorySchema::options(); - - return self::getSchemaFromEnum($enumOptions); - } - - public static function getViolencesTypesSchema(): array - { - $enumOptions = ViolencesTypesSchema::options(); - - return self::getSchemaFromEnum($enumOptions); - } - - public static function getRiskFactorsSchema(): array - { - $enumOptions = RiskFactorsSchema::options(); - - return self::getSchemaFromEnum($enumOptions); - } - - public static function getVictimPerceptionOfTheRiskSchema(): array - { - $enumOptions = VictimPerceptionOfTheRiskSchema::options(); - - return self::getSchemaFromEnum($enumOptions); - } - - public static function getAggravatingFactorsSchema(): array - { - $enumOptions = AggravatingFactorsSchema::options(); - - return self::getSchemaFromEnum($enumOptions); - } - - public static function getSocialSupportSchema(): array - { - return [ - Group::make() - ->schema([ - Select::make('extended_family_can_provide') - ->label(__('beneficiary.section.initial_evaluation.labels.extended_family_can_provide')) - ->multiple() - ->options(Helps::options()) - ->disabled(fn (Get $get) => $get('extended_family_can_not_provide')), - - Checkbox::make('extended_family_can_not_provide') - ->label(__('beneficiary.section.initial_evaluation.labels.extended_family_can_not_provide')) - ->afterStateUpdated( - function ($state, Get $get, Set $set) { - if ($state) { - $set('extended_family_can_provide_old_values', $get('extended_family_can_provide')); - $set('extended_family_can_provide', null); - - return; - } - - $set('extended_family_can_provide', $get('extended_family_can_provide_old_values')); - } - ) - ->live(), - - Hidden::make('extended_family_can_provide_old_values'), - ]), - - Group::make() - ->schema([ - Select::make('friends_can_provide') - ->label(__('beneficiary.section.initial_evaluation.labels.friends_can_provide')) - ->multiple() - ->options(Helps::options()) - ->disabled(fn (Get $get) => $get('friends_can_not_provide')), - - Checkbox::make('friends_can_not_provide') - ->label(__('beneficiary.section.initial_evaluation.labels.friends_can_not_provide')) - ->afterStateUpdated( - function ($state, Get $get, Set $set) { - if ($state) { - $set('friends_can_provide_old_values', $get('friends_can_provide')); - $set('friends_can_provide', null); - - return; - } - - $set('friends_can_provide', $get('friends_can_provide_old_values')); - } - ) - ->live(), - - Hidden::make('friends_can_provide_old_values'), - - ]), - - ]; + return $schema->components(InitialEvaluationSchema::getRiskFactorsFormComponents()); } public static function getInfoListSchema(): array { return [ - InfolistGroup::make() + Group::make() ->relationship('riskFactors') ->schema([ - InfolistSection::make(fn (Beneficiary $record) => self::getViolenceHeading($record)) + Section::make(fn (Beneficiary $record) => self::getViolenceHeading($record)) ->collapsed() ->schema(self::getViolenceHistoryInfolistSchema()), - InfolistSection::make(fn (Beneficiary $record) => self::getViolencesTypesHeading($record)) + Section::make(fn (Beneficiary $record) => self::getViolencesTypesHeading($record)) ->collapsed() ->schema(self::getViolencesTypesInfolistSchema()), - InfolistSection::make(fn (Beneficiary $record) => self::getRiskFactorsHeading($record)) + Section::make(fn (Beneficiary $record) => self::getRiskFactorsHeading($record)) ->collapsed() ->schema(self::getRiskFactorsInfolistSchema()), - InfolistSection::make(fn (Beneficiary $record) => self::getVictimPerceptionOfTherRiskHeading($record)) + Section::make(fn (Beneficiary $record) => self::getVictimPerceptionOfTherRiskHeading($record)) ->collapsed() ->schema(self::getVictimPerceptionOfTheRiskInfolistSchema()), - InfolistSection::make(fn (Beneficiary $record) => self::getAggravatingFactorsHeading($record)) + Section::make(fn (Beneficiary $record) => self::getAggravatingFactorsHeading($record)) ->collapsed() ->schema(self::getAggravatingFactorsInfolistSchema()), - InfolistSection::make(__('beneficiary.section.initial_evaluation.heading.social_support')) + Section::make(__('beneficiary.section.initial_evaluation.heading.social_support')) ->collapsed() ->columns() ->schema(self::getSocialSupportInfolistSchema()), diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditViolence.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditViolence.php index 1512889a..4037d46c 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditViolence.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/EditViolence.php @@ -4,19 +4,12 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use App\Filament\Organizations\Schemas\BeneficiaryResource\InitialEvaluationSchema; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToInitialEvaluation; -use App\Enums\Frequency; -use App\Enums\Violence; use App\Filament\Organizations\Resources\BeneficiaryResource; -use App\Forms\Components\Select; -use App\Infolists\Components\EnumEntry; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; -use Filament\Forms\Form; -use Filament\Infolists\Components\Group; -use Filament\Infolists\Components\TextEntry; +use Filament\Schemas\Schema; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -44,73 +37,13 @@ protected function getTabSlug(): string return Str::slug(__('beneficiary.wizard.violence.label')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema()); - } - - public static function getSchema(): array - { - return [ - Section::make() - ->relationship('violence') - ->maxWidth('3xl') - ->columns() - ->schema([ - Select::make('violence_types') - ->label(__('beneficiary.section.initial_evaluation.labels.violence_type')) - ->placeholder(__('beneficiary.placeholder.violence_type')) - ->options(Violence::options()) - ->multiple() - ->required(), - - Select::make('violence_primary_type') - ->label(__('beneficiary.section.initial_evaluation.labels.violence_primary_type')) - ->placeholder(__('beneficiary.placeholder.violence_primary_type')) - ->options(Violence::options()) - ->required(), - - Select::make('frequency_violence') - ->label(__('beneficiary.section.initial_evaluation.labels.frequency_violence')) - ->placeholder(__('beneficiary.placeholder.frequency_violence')) - ->options(Frequency::options()) - ->required(), - - RichEditor::make('description') - ->label(__('beneficiary.section.initial_evaluation.labels.description')) - ->placeholder(__('beneficiary.placeholder.description')) - ->helperText(__('beneficiary.helper_text.violence_description')) - ->columnSpanFull() - ->maxLength(5000), - ]), - ]; + return $schema->components(InitialEvaluationSchema::getViolenceFormComponents()); } public static function getInfoListSchema(): array { - return [ - Group::make() - ->relationship('violence') - ->columns() - ->schema([ - TextEntry::make('violence_types') - ->label(__('beneficiary.section.initial_evaluation.labels.violence_type')), - - EnumEntry::make('violence_primary_type') - ->label(__('beneficiary.section.initial_evaluation.labels.violence_primary_type')) - ->placeholder(__('beneficiary.placeholder.violence_primary_type')), - - EnumEntry::make('frequency_violence') - ->label(__('beneficiary.section.initial_evaluation.labels.frequency_violence')) - ->placeholder(__('beneficiary.placeholder.frequency_violence')), - - TextEntry::make('description') - ->label(__('beneficiary.section.initial_evaluation.labels.description')) - ->placeholder(__('beneficiary.placeholder.description')) - ->columnSpanFull() - ->html(), - ]), - - ]; + return InitialEvaluationSchema::getViolenceInfolistComponents(); } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/ViewInitialEvaluation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/ViewInitialEvaluation.php index 50a3d533..6ea466be 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/ViewInitialEvaluation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/InitialEvaluation/ViewInitialEvaluation.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages\InitialEvaluation; +use Filament\Schemas\Schema; +use Filament\Schemas\Components\Tabs\Tab; use App\Actions\BackAction; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Filament\Organizations\Resources\BeneficiaryResource\Pages\ViewBeneficiaryIdentity; @@ -11,9 +13,9 @@ use App\Infolists\Components\Notice; use App\Infolists\Components\SectionHeader; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Infolists\Components\Group; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -42,14 +44,14 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Tabs::make() ->persistTabInQueryString() ->columnSpanFull() ->schema([ - Tabs\Tab::make(__('beneficiary.wizard.details.label')) + Tab::make(__('beneficiary.wizard.details.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.details.label')) @@ -62,15 +64,15 @@ public function infolist(Infolist $infolist): Infolist ]) ->schema(EditEvaluationDetails::getInfoListSchema())]), - Tabs\Tab::make(__('beneficiary.section.identity.tab.beneficiary')) + Tab::make(__('beneficiary.section.identity.tab.beneficiary')) ->maxWidth('3xl') ->schema(ViewBeneficiaryIdentity::identitySchemaForOtherPage($this->record)), - Tabs\Tab::make(__('beneficiary.section.identity.tab.children')) + Tab::make(__('beneficiary.section.identity.tab.children')) ->maxWidth('3xl') ->schema(ViewBeneficiaryIdentity::childrenSchemaForOtherPage($this->record)), - Tabs\Tab::make(__('beneficiary.wizard.violence.label')) + Tab::make(__('beneficiary.wizard.violence.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.violence.label')) @@ -82,7 +84,7 @@ public function infolist(Infolist $infolist): Infolist )), ]) ->schema(EditViolence::getInfoListSchema())]), - Tabs\Tab::make(__('beneficiary.wizard.risk_factors.label')) + Tab::make(__('beneficiary.wizard.risk_factors.label')) ->maxWidth('3xl') ->schema([ Section::make() @@ -102,7 +104,7 @@ public function infolist(Infolist $infolist): Infolist ...EditRiskFactors::getInfoListSchema(), ]), ]), - Tabs\Tab::make(__('beneficiary.wizard.requested_services.label')) + Tab::make(__('beneficiary.wizard.requested_services.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.requested_services.label')) @@ -114,7 +116,7 @@ public function infolist(Infolist $infolist): Infolist )), ]) ->schema($this->getRequestedServicesInfoListSchema())]), - Tabs\Tab::make(__('beneficiary.wizard.beneficiary_situation.label')) + Tab::make(__('beneficiary.wizard.beneficiary_situation.label')) ->maxWidth('3xl') ->schema([ Section::make(__('beneficiary.wizard.beneficiary_situation.label')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListBeneficiaries.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListBeneficiaries.php index 0b583c19..5936ee47 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListBeneficiaries.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListBeneficiaries.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\BeneficiaryResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -21,7 +22,7 @@ public function getBreadcrumbs(): array protected function getHeaderActions(): array { return [ - Actions\CreateAction::make() + CreateAction::make() ->label(__('beneficiary.action.create')), ]; } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListSpecialists.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListSpecialists.php index 0bca56f5..94c38b56 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListSpecialists.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ListSpecialists.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use App\Filament\Organizations\Resources\BeneficiaryResource\Widgets\ListSpecialistsWidget; use App\Actions\BackAction; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; @@ -31,11 +32,11 @@ protected function getHeaderActions(): array protected function getHeaderWidgets(): array { return [ - BeneficiaryResource\Widgets\ListSpecialistsWidget::class, + ListSpecialistsWidget::class, ]; } - public function getHeaderWidgetsColumns(): int|string|array + public function getHeaderWidgetsColumns(): int|array { return 1; } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiary.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiary.php index 5aae04ae..eab261e0 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiary.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiary.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; +use Filament\Support\Enums\TextSize; use App\Actions\BackAction; use App\Enums\ActivityDescription; use App\Enums\AddressType; @@ -29,11 +31,10 @@ use Filament\Actions\ActionGroup; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\Placeholder; -use Filament\Infolists\Components\Actions; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Components\TextEntry\TextEntrySize; use Filament\Infolists\Infolist; @@ -107,7 +108,7 @@ protected function getHeaderActions(): array && $record->status !== CaseStatus::ARCHIVED ) ->modalHeading(__('beneficiary.section.identity.headings.reactivate_modal')) - ->form([ + ->schema([ Placeholder::make('reactivate_text_1') ->hiddenLabel() ->content(__('beneficiary.placeholder.reactivate_text_1')), @@ -152,11 +153,11 @@ public function getTitle(): string|Htmlable ])); } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist + return $schema ->columns() - ->schema([ + ->components([ $this->identitySectionSection(), $this->personalInformationSection(), $this->initialEvaluation(), @@ -238,7 +239,7 @@ protected function personalInformationSection(): Section 'class' => 'h-full', ]) ->schema([ - Grid::make() + \Filament\Schemas\Components\Grid::make() ->relationship('flowPresentation') ->schema([ EnumEntry::make('presentation_mode') @@ -288,13 +289,13 @@ protected function personalInformationSection(): Section ->schema([ EnumEntry::make('has_police_reports') ->label(__('field.has_police_reports')) - ->suffix(fn (Beneficiary $record, $state) => Ternary::isYes($state) - ? " ({$record->antecedents->police_report_count})" : null), + ->suffix(fn (\App\Models\BeneficiaryAntecedents $record, $state) => Ternary::isYes($state) + ? " ({$record->police_report_count})" : null), EnumEntry::make('has_medical_reports') ->label(__('field.has_medical_reports')) - ->suffix(fn (Beneficiary $record, $state) => Ternary::isYes($state) - ? " ({$record->antecedents->medical_report_count})" : null), + ->suffix(fn (\App\Models\BeneficiaryAntecedents $record, $state) => Ternary::isYes($state) + ? " ({$record->medical_report_count})" : null), ]), ]); } @@ -334,19 +335,23 @@ private function initialEvaluation(): Section ->default(__('beneficiary.helper_text.initial_evaluation')) ->alignCenter() ->weight(FontWeight::SemiBold) - ->size(TextEntrySize::Medium), + ->size(TextSize::Medium), TextEntry::make('empty_state_description') ->hiddenLabel() ->default(__('beneficiary.helper_text.initial_evaluation_2')) ->alignCenter() ->color(Color::Gray) - ->size(TextEntrySize::Small), - Actions::make([ - Actions\Action::make('create_initial_evaluation') - ->label(__('beneficiary.action.start_evaluation')) - ->url(fn (Beneficiary $record) => BeneficiaryResource::getUrl('create_initial_evaluation', ['record' => $record])) - ->outlined(), - ]) + ->size(TextSize::Small), + Placeholder::make('actions_placeholder') + ->hiddenLabel() + ->content( + ActionGroup::make([ + Action::make('create_initial_evaluation') + ->label(__('beneficiary.action.start_evaluation')) + ->url(fn (Beneficiary $record) => BeneficiaryResource::getUrl('create_initial_evaluation', ['record' => $record])) + ->outlined(), + ]) + ) ->alignCenter(), ]), ]); @@ -381,19 +386,23 @@ private function detailedEvaluation(): Section ->default(__('beneficiary.helper_text.detailed_evaluation')) ->alignCenter() ->weight(FontWeight::SemiBold) - ->size(TextEntrySize::Medium), + ->size(TextSize::Medium), TextEntry::make('empty_state_description') ->hiddenLabel() ->default(__('beneficiary.helper_text.detailed_evaluation_2')) ->alignCenter() ->color(Color::Gray) - ->size(TextEntrySize::Small), - Actions::make([ - Actions\Action::make('create_detailed_evaluation') - ->label(__('beneficiary.action.start_evaluation')) - ->url(fn (Beneficiary $record) => BeneficiaryResource::getUrl('create_detailed_evaluation', ['record' => $record])) - ->outlined(), - ]) + ->size(TextSize::Small), + Placeholder::make('actions_placeholder') + ->hiddenLabel() + ->content( + ActionGroup::make([ + Action::make('create_detailed_evaluation') + ->label(__('beneficiary.action.start_evaluation')) + ->url(fn (Beneficiary $record) => BeneficiaryResource::getUrl('create_detailed_evaluation', ['record' => $record])) + ->outlined(), + ]) + ) ->alignCenter(), ]), ]); @@ -407,7 +416,7 @@ protected function getFooterWidgets(): array CloseFileWidget::class, CaseTeamListWidget::class, DocumentsListWidget::class, - RelatedCases::class, +// RelatedCases::class, ]; } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryIdentity.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryIdentity.php index 962a57cd..0fa8f8df 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryIdentity.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryIdentity.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Enums\AddressType; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -16,10 +17,10 @@ use App\Models\Beneficiary; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Infolists\Components\Actions\Action; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; -use Filament\Infolists\Components\Tabs\Tab; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; +use Filament\Schemas\Components\Tabs\Tab; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -48,9 +49,9 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist + return $schema ->schema([ Tabs::make() ->persistTabInQueryString() @@ -92,7 +93,7 @@ public static function identitySchemaForOtherPage(Beneficiary $record): array ->state(__('beneficiary.section.identity.heading_description')) ->color('primary') ->action( - Action::make('view') + \Filament\Actions\Action::make('view') ->label(__('beneficiary.section.identity.title')) ->url(self::$resource::getUrl('view_identity', ['record' => $record])) ->link(), @@ -229,7 +230,7 @@ public static function childrenSchemaForOtherPage(Beneficiary $record): array ->state(__('beneficiary.section.identity.heading_description')) ->color('primary') ->action( - Action::make('view') + \Filament\Actions\Action::make('view') ->label(__('beneficiary.section.identity.title')) ->url(self::$resource::getUrl('view_identity', ['record' => $record])) ->link(), diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryPersonalInformation.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryPersonalInformation.php index 1aa3cddb..47c287a0 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryPersonalInformation.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Pages/ViewBeneficiaryPersonalInformation.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Enums\AggressorRelationship; use App\Enums\Diseases; @@ -15,11 +16,11 @@ use App\Models\Aggressor; use App\Models\Beneficiary; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Infolists\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; -use Filament\Infolists\Components\Tabs\Tab; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; +use Filament\Schemas\Components\Tabs\Tab; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -48,9 +49,9 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist + return $schema ->columns() ->schema(static::getPersonalInformationFormSchema()); } @@ -124,17 +125,17 @@ protected static function beneficiarySection(): array TextEntry::make('observations_chronic_diseases') ->label(__('beneficiary.section.personal_information.label.observations_chronic_diseases')) ->columnSpanFull() - ->visible(fn (Beneficiary $record) => $record->details->health_status?->contains(Diseases::CHRONIC_DISEASES)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => $record->health_status?->contains(Diseases::CHRONIC_DISEASES)), TextEntry::make('observations_degenerative_diseases') ->label(__('beneficiary.section.personal_information.label.observations_degenerative_diseases')) ->columnSpanFull() - ->visible(fn (Beneficiary $record) => $record->details->health_status?->contains(Diseases::DEGENERATIVE_DISEASES)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => $record->health_status?->contains(Diseases::DEGENERATIVE_DISEASES)), TextEntry::make('observations_mental_illness') ->label(__('beneficiary.section.personal_information.label.observations_mental_illness')) ->columnSpanFull() - ->visible(fn (Beneficiary $record) => $record->details->health_status?->contains(Diseases::MENTAL_ILLNESSES)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => $record->health_status?->contains(Diseases::MENTAL_ILLNESSES)), ]), Grid::make() @@ -144,7 +145,7 @@ protected static function beneficiarySection(): array TextEntry::make('drug_types') ->label(__('beneficiary.section.personal_information.label.drug_types')) - ->visible(fn (Beneficiary $record) => Ternary::isYes($record->details->drug_consumption)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => Ternary::isYes($record->drug_consumption)), ]), Grid::make() @@ -178,15 +179,15 @@ protected static function beneficiarySection(): array TextEntry::make('type_of_disability') ->label(__('beneficiary.section.personal_information.label.type_of_disability')) - ->visible(fn (Beneficiary $beneficiary) => Ternary::isYes($beneficiary->details->disabilities)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => Ternary::isYes($record->disabilities)), TextEntry::make('degree_of_disability') ->label(__('beneficiary.section.personal_information.label.degree_of_disability')) - ->visible(fn (Beneficiary $beneficiary) => Ternary::isYes($beneficiary->details->disabilities)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => Ternary::isYes($record->disabilities)), TextEntry::make('observations_disability') ->label(__('beneficiary.section.personal_information.label.observations_disability')) - ->visible(fn (Beneficiary $beneficiary) => Ternary::isYes($beneficiary->details->disabilities)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => Ternary::isYes($record->disabilities)), ]), Grid::make() @@ -196,7 +197,7 @@ protected static function beneficiarySection(): array TextEntry::make('medication_observations') ->label(__('beneficiary.section.personal_information.label.medication_observations')) - ->visible(fn (Beneficiary $beneficiary) => Ternary::isYes($beneficiary->details->other_current_medication)), + ->visible(fn (\App\Models\BeneficiaryDetails $record) => Ternary::isYes($record->other_current_medication)), ]), Grid::make() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/RelationManagers/DocumentsRelationManager.php b/app/Filament/Organizations/Resources/BeneficiaryResource/RelationManagers/DocumentsRelationManager.php new file mode 100644 index 00000000..d53603ea --- /dev/null +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/RelationManagers/DocumentsRelationManager.php @@ -0,0 +1,34 @@ +relationship('documents') + ->inverseRelationship('beneficiary'); + } + + public static function getRecordTitle(Model|null $record): string|null|Htmlable + { + return $record->name; + } + + public static function form(Schema $schema): Schema + { + return DocumentResourceSchema::form($schema); + } + + public static function table(Table $table): Table + { + return DocumentResourceSchema::table($table); + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListDocuments::route('/'), + 'view' => Pages\ViewDocument::route('/{record}'), + ]; + } +} diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ListDocuments.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ListDocuments.php new file mode 100644 index 00000000..62dcc4e2 --- /dev/null +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ListDocuments.php @@ -0,0 +1,85 @@ +disableLogging(); + } + + public function getBreadcrumbs(): array + { + $parentRecord = $this->getParentRecord(); + return BeneficiaryBreadcrumb::make($parentRecord) + ->getBreadcrumbs('documents.index'); + } + + public function getTitle(): string|Htmlable + { + return __('beneficiary.section.documents.title.page'); + } + + protected function getHeaderActions(): array + { + $parentRecord = $this->getParentRecord(); + + return [ + BackAction::make() + ->url(BeneficiaryResource::getUrl('view', ['record' => $parentRecord])), + + Actions\CreateAction::make() + ->modalHeading(__('beneficiary.section.documents.title.add_modal')) + ->label(__('beneficiary.section.documents.actions.add')) + ->createAnother(false) + ->modalSubmitActionLabel(__('beneficiary.section.documents.actions.create')) + ->modalCancelActionLabel(__('general.action.cancel')) + ->mutateDataUsing(function (array $data) use ($parentRecord) { + $data['beneficiary_id'] = $parentRecord->id; + return $data; + }) + ->relationship(null) + ->successRedirectUrl(fn (Document $record) => static::getResource()::getUrl('view', [ + 'beneficiary' => $parentRecord, + 'record' => $record, + ])), + ]; + } + + public function table(Table $table): Table + { + return \App\Filament\Organizations\Schemas\DocumentResourceSchema::table($table) + ->emptyStateActions([ + \Filament\Actions\CreateAction::make() + ->modalHeading(__('beneficiary.section.documents.title.add_modal')) + ->label(__('beneficiary.section.documents.actions.add')) + ->createAnother(false) + ->outlined() + ->size(Size::ExtraLarge) + ->modalSubmitActionLabel(__('beneficiary.section.documents.actions.create')) + ->modalCancelActionLabel(__('general.action.cancel')) + ->mutateDataUsing(function (array $data) { + $data['beneficiary_id'] = $this->getParentRecord()->id; + return $data; + }) + ->successRedirectUrl(fn (Document $record) => static::getResource()::getUrl('view', [ + 'record' => $record, + ])), + ]); + } +} diff --git a/app/Filament/Organizations/Resources/DocumentResource/Pages/ViewDocument.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ViewDocument.php similarity index 78% rename from app/Filament/Organizations/Resources/DocumentResource/Pages/ViewDocument.php rename to app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ViewDocument.php index dadd7788..ee9c4823 100644 --- a/app/Filament/Organizations/Resources/DocumentResource/Pages/ViewDocument.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Resources/DocumentResource/Pages/ViewDocument.php @@ -2,30 +2,26 @@ declare(strict_types=1); -namespace App\Filament\Organizations\Resources\DocumentResource\Pages; +namespace App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; -use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; -use App\Filament\Organizations\Resources\DocumentResource; use App\Infolists\Components\DocumentPreview; use App\Infolists\Components\EnumEntry; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Actions\Action; use Filament\Actions\DeleteAction; use Filament\Actions\EditAction; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; -use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; use Filament\Support\Enums\Alignment; use Illuminate\Contracts\Support\Htmlable; class ViewDocument extends ViewRecord { - use HasParentResource; - - protected static string $resource = DocumentResource::class; + protected static string $resource = \App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource::class; public function getTitle(): string|Htmlable { @@ -34,15 +30,20 @@ public function getTitle(): string|Htmlable public function getBreadcrumbs(): array { - return BeneficiaryBreadcrumb::make($this->parent) + $parentRecord = $this->getParentRecord(); + return BeneficiaryBreadcrumb::make($parentRecord) ->getBreadcrumbs('documents.index'); } protected function getHeaderActions(): array { + $parentRecord = $this->getParentRecord(); + return [ BackAction::make() - ->url(BeneficiaryResource::getUrl('documents.index', ['parent' => $this->parent])), + ->url(static::getResource()::getUrl('index', [ + 'beneficiary' => $parentRecord, + ])), DeleteAction::make() ->label(__('beneficiary.section.documents.actions.delete')) @@ -76,9 +77,9 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->hiddenLabel() ->columns() @@ -98,10 +99,11 @@ public function infolist(Infolist $infolist): Infolist protected function configureDeleteAction(DeleteAction $action): void { $resource = static::getResource(); + $parentRecord = $this->getParentRecord(); $action->authorize($resource::canDelete($this->getRecord())) - ->successRedirectUrl(static::getParentResource()::getUrl('documents.index', [ - 'parent' => $this->parent, + ->successRedirectUrl(static::getResource()::getUrl('index', [ + 'beneficiary' => $parentRecord, ])); } } diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CaseTeamListWidget.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CaseTeamListWidget.php index 5ba440a3..07128f5c 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CaseTeamListWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CaseTeamListWidget.php @@ -32,7 +32,7 @@ public function table(Table $table): Table ->heading(__('beneficiary.section.specialists.title')) ->paginated(false) ->headerActions([ - Action::make('view') + \Filament\Actions\Action::make('view') ->label(__('general.action.view_details')) ->link() ->url(fn () => BeneficiaryResource::getUrl('view_specialists', ['record' => $this->record])), diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CloseFileWidget.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CloseFileWidget.php index 698385df..9a453890 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CloseFileWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/CloseFileWidget.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Widgets; +use Filament\Actions\Action; use App\Enums\CaseStatus; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Models\Beneficiary; @@ -27,7 +28,7 @@ public function table(Table $table): Table ->paginated(false) ->heading(__('beneficiary.section.close_file.headings.widget')) ->headerActions([ - Tables\Actions\Action::make('view_monitoring') + Action::make('view_monitoring') ->label(__('general.action.view_details')) ->link() ->visible(fn () => $this->record->closeFile) @@ -42,7 +43,7 @@ public function table(Table $table): Table ]) ->emptyStateHeading(__('beneficiary.section.close_file.headings.widget_empty_state')) ->emptyStateActions([ - Tables\Actions\Action::make('create_close_file') + Action::make('create_close_file') ->label(__('beneficiary.section.close_file.actions.create_widget')) ->outlined() ->disabled(fn () => ! CaseStatus::isValue($this->record->status, CaseStatus::CLOSED)) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/DocumentsListWidget.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/DocumentsListWidget.php index 000e51ad..0b18242a 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/DocumentsListWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/DocumentsListWidget.php @@ -4,9 +4,11 @@ namespace App\Filament\Organizations\Resources\BeneficiaryResource\Widgets; +use Filament\Tables\Columns\TextColumn; +use Filament\Actions\CreateAction; use App\Concerns\HasViewContentFooter; use App\Filament\Organizations\Resources\BeneficiaryResource; -use App\Filament\Organizations\Resources\DocumentResource; +use App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource; use App\Models\Beneficiary; use App\Models\Document; use Filament\Tables; @@ -28,18 +30,20 @@ public function table(Table $table): Table ->query(fn () => $this->record->documents()->limit($this->limit)) ->heading(__('beneficiary.section.documents.title.page')) ->headerActions([ - Action::make('view') + \Filament\Actions\Action::make('view') ->label(__('general.action.view_details')) - ->url(fn () => BeneficiaryResource::getUrl('documents.index', ['parent' => $this->record])) + ->url(fn () => DocumentResource::getUrl('index', [ + 'beneficiary' => $this->record, + ])) ->link() ->visible(fn () => $this->record->documents->count()), ]) ->paginated(false) ->columns([ - Tables\Columns\TextColumn::make('type') + TextColumn::make('type') ->label(__('beneficiary.section.documents.labels.type')), - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->label(__('beneficiary.section.documents.labels.name')), ]) ->contentFooter( @@ -49,21 +53,21 @@ public function table(Table $table): Table ->emptyStateHeading(__('beneficiary.helper_text.documents')) ->emptyStateDescription(__('beneficiary.helper_text.documents_2')) ->emptyStateActions([ - Tables\Actions\CreateAction::make() - ->form(DocumentResource::getSchema()) + CreateAction::make() + ->schema(\App\Filament\Organizations\Schemas\DocumentResourceSchema::getFormComponents()) ->modalHeading(__('beneficiary.section.documents.title.add_modal')) ->label(__('beneficiary.section.documents.actions.add')) ->outlined() ->createAnother(false) ->modalSubmitActionLabel(__('beneficiary.section.documents.actions.create')) ->modalCancelActionLabel(__('general.action.cancel')) - ->mutateFormDataUsing(function (array $data) { + ->mutateDataUsing(function (array $data) { $data['beneficiary_id'] = $this->record->id; return $data; }) - ->successRedirectUrl(fn (Document $record) => BeneficiaryResource::getUrl('documents.view', [ - 'parent' => $this->record, + ->successRedirectUrl(fn (Document $record) => DocumentResource::getUrl('view', [ + 'beneficiary' => $this->record, 'record' => $record, ])), ]); diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/IntervetnionPlanWidget.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/IntervetnionPlanWidget.php index e3cef910..353e9257 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/IntervetnionPlanWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/IntervetnionPlanWidget.php @@ -34,6 +34,9 @@ public function table(Table $table): Table 'specialist.user', 'specialist.role', 'nextMeeting', + 'interventionService', + 'interventionPlan', + 'beneficiary', ]) ->withCount('meetings') ?: $this->record->interventionPlan() @@ -57,20 +60,24 @@ public function table(Table $table): Table ->defaultPaginationPageOption(5) ->paginationPageOptions([5]) ->heading(__('intervention_plan.headings.table')) - ->actions([ - ViewAction::make('view_intervention') + ->recordActions([ + \Filament\Actions\ViewAction::make('view_intervention') ->label(__('intervention_plan.actions.view_intervention')) ->url(fn (BeneficiaryIntervention $record) => InterventionServiceResource::getUrl('view_intervention', [ - 'parent' => $record->intervention_service_id, + 'beneficiary' => $record->beneficiary, + 'intervention_plan' => $record->interventionPlan, + 'parent' => $record->interventionService, 'record' => $record, ])), ]) ->recordUrl(fn (BeneficiaryIntervention $record) => InterventionServiceResource::getUrl('view_intervention', [ - 'parent' => $record->intervention_service_id, + 'beneficiary' => $record->beneficiary, + 'intervention_plan' => $record->interventionPlan, + 'parent' => $record->interventionService, 'record' => $record, ])) ->headerActions([ - Action::make('view_intervention_plan') + \Filament\Actions\Action::make('view_intervention_plan') ->label(__('intervention_plan.actions.view_intervention_plan')) ->visible((bool) $this->record->interventionPlan) ->link() @@ -93,7 +100,7 @@ public function table(Table $table): Table ) ->emptyStateIcon('heroicon-o-presentation-chart-bar') ->emptyStateActions([ - Action::make('create_intervention_plan') + \Filament\Actions\Action::make('create_intervention_plan') ->label(__('intervention_plan.actions.create')) ->hidden((bool) $this->record->interventionPlan) ->outlined() diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/ListSpecialistsWidget.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/ListSpecialistsWidget.php index e954000c..f21fad92 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/ListSpecialistsWidget.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/ListSpecialistsWidget.php @@ -14,8 +14,8 @@ use App\Tables\Actions\EditAction; use Filament\Facades\Filament; use Filament\Forms\Components\Hidden; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Support\Colors\Color; use Filament\Support\Enums\Alignment; use Filament\Tables\Actions\CreateAction; @@ -52,16 +52,16 @@ public function table(Table $table): Table ->label(__('beneficiary.section.specialists.labels.status')), ]) ->headerActions([ - CreateAction::make() - ->form($this->getFormSchema()) + \Filament\Actions\CreateAction::make() + ->schema($this->getFormSchema()) ->label(__('beneficiary.section.specialists.add_action')) ->modalHeading(__('beneficiary.section.specialists.heading.add_modal')) ->createAnother(false) ->modalSubmitActionLabel(), ]) - ->actions([ + ->recordActions([ EditAction::make() - ->form($this->getFormSchema()) + ->schema($this->getFormSchema()) ->fillForm(function (Specialist $record) { if (! $record->role_id) { $record->role_id = -1; @@ -71,7 +71,7 @@ public function table(Table $table): Table }) ->modalHeading(__('beneficiary.section.specialists.heading.edit_modal')) ->extraModalFooterActions([ - DeleteAction::make() + \Filament\Actions\DeleteAction::make() ->cancelParentActions() ->label(__('beneficiary.section.specialists.action.delete')) ->modalHeading(__('beneficiary.section.specialists.heading.delete_modal')) diff --git a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/RelatedCases.php b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/RelatedCases.php index ac1991d2..f2ed1668 100644 --- a/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/RelatedCases.php +++ b/app/Filament/Organizations/Resources/BeneficiaryResource/Widgets/RelatedCases.php @@ -17,7 +17,7 @@ class RelatedCases extends BaseWidget { public ?Model $record = null; - protected static string $view = 'widgets.related-cases-table'; + protected string $view = 'widgets.related-cases-table'; protected int | string | array $columnSpan = 2; @@ -60,8 +60,8 @@ public function table(Table $table): Table ]) ->heading(__('beneficiary.labels.related_cases')) ->paginated(false) - ->actions([ - ViewAction::make() + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_details')) ->color('primary') ->url(fn (Beneficiary $record) => BeneficiaryResource::getUrl('view', ['record' => $record->id])), diff --git a/app/Filament/Organizations/Resources/CommunityProfileResource.php b/app/Filament/Organizations/Resources/CommunityProfileResource.php index 4815d2fd..7e53c7a4 100644 --- a/app/Filament/Organizations/Resources/CommunityProfileResource.php +++ b/app/Filament/Organizations/Resources/CommunityProfileResource.php @@ -4,27 +4,18 @@ namespace App\Filament\Organizations\Resources; +use App\Filament\Organizations\Resources\CommunityProfileResource\Pages\EditCommunityProfile; +use App\Filament\Organizations\Schemas\CommunityProfileResourceSchema; use App\Filament\Organizations\Resources\CommunityProfileResource\Pages; -use App\Forms\Components\Select; -use App\Forms\Components\TableRepeater; use App\Models\CommunityProfile; -use App\Models\Service; -use Awcodes\TableRepeater\Header; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Form; use Filament\Resources\Resource; +use Filament\Schemas\Schema; class CommunityProfileResource extends Resource { protected static ?string $model = CommunityProfile::class; - protected static ?string $navigationIcon = 'heroicon-o-check-badge'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-check-badge'; protected static bool $isScopedToTenant = false; @@ -50,108 +41,12 @@ public static function getNavigationLabel(): string public static function getPages(): array { return [ - 'index' => Pages\EditCommunityProfile::route('/'), + 'index' => EditCommunityProfile::route('/'), ]; } - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - $services = Service::pluck('name', 'id'); - - return $form - ->schema([ - Section::make() - ->columns(4) - ->schema([ - Group::make() - ->columnSpan(3) - ->schema([ - TextInput::make('name') - ->label(__('community.field.name')) - ->placeholder(__('community.placeholder.name')) - ->maxLength(200) - ->required(), - - TableRepeater::make('services') - ->relationship() - ->reorderable(false) - ->addActionLabel(__('service.action.create')) - ->minItems(1) - ->headers([ - Header::make('service_id') - ->label(__('community.field.service')) - ->markAsRequired(), - - Header::make('is_visible') - ->label(__('community.field.service_visible')), - - Header::make('is_available') - ->label(__('community.field.service_available')), - ]) - ->schema([ - Hidden::make('model_type') - ->default(app(CommunityProfile::class)->getMorphClass()), - - Select::make('service_id') - ->label(__('community.field.service')) - ->options($services) - ->required(), - - Toggle::make('is_visible') - ->label(__('community.field.service_visible')), - - Toggle::make('is_available') - ->label(__('community.field.service_available')), - - ]), - - Select::make('counties') - ->relationship('counties', 'name') - ->label(__('community.field.location')) - ->placeholder(__('community.placeholder.location')) - ->multiple() - ->preload(), - ]), - - RichEditor::make('description') - ->label(__('community.field.description')) - ->placeholder(__('community.placeholder.description')) - ->toolbarButtons([ - 'bold', - 'bulletList', - 'italic', - 'link', - 'orderedList', - 'redo', - 'strike', - 'underline', - 'undo', - ]) - ->columnSpanFull(), - - SpatieMediaLibraryFileUpload::make('logo') - ->label(__('community.field.logo')) - ->helperText(__('community.help.logo')) - ->image() - ->collection('logo') - ->conversion('large') - ->columnSpanFull(), - - TextInput::make('email') - ->label(__('community.field.email')) - ->placeholder(__('placeholder.email')) - ->email(), - - TextInput::make('phone') - ->label(__('community.field.phone')) - ->placeholder(__('placeholder.phone')) - ->tel(), - - TextInput::make('website') - ->label(__('community.field.website')) - ->placeholder(__('placeholder.url')) - ->url(), - ]), - ]); + return CommunityProfileResourceSchema::form($schema); } } diff --git a/app/Filament/Organizations/Resources/CommunityProfileResource/Pages/EditCommunityProfile.php b/app/Filament/Organizations/Resources/CommunityProfileResource/Pages/EditCommunityProfile.php index 5cd1205a..18523e8e 100644 --- a/app/Filament/Organizations/Resources/CommunityProfileResource/Pages/EditCommunityProfile.php +++ b/app/Filament/Organizations/Resources/CommunityProfileResource/Pages/EditCommunityProfile.php @@ -14,7 +14,7 @@ class EditCommunityProfile extends EditRecord { protected static string $resource = CommunityProfileResource::class; - protected static string $view = 'filament.organizations.pages.empty-page'; + protected string $view = 'filament.organizations.pages.empty-page'; public function getBreadcrumbs(): array { diff --git a/app/Filament/Organizations/Resources/CommunityResource.php b/app/Filament/Organizations/Resources/CommunityResource.php index 3f8f65f8..94a628f9 100644 --- a/app/Filament/Organizations/Resources/CommunityResource.php +++ b/app/Filament/Organizations/Resources/CommunityResource.php @@ -4,33 +4,19 @@ namespace App\Filament\Organizations\Resources; -use App\Filament\Organizations\Resources\CommunityResource\Pages; +use App\Filament\Organizations\Schemas\CommunityResourceSchema; +use App\Filament\Organizations\Resources\CommunityResource\Pages\ListCommunityProfiles; +use App\Filament\Organizations\Resources\CommunityResource\Pages\ViewCommunityProfile; use App\Models\CommunityProfile; -use App\Tables\Columns\ServiceChipsColumn; -use App\Tables\Filters\ServicesFilter; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\SpatieMediaLibraryImageEntry; -use Filament\Infolists\Components\Split as InfolistSplit; -use Filament\Infolists\Components\TextEntry; -use Filament\Infolists\Infolist; use Filament\Resources\Resource; -use Filament\Tables; -use Filament\Tables\Columns\Layout\Split; -use Filament\Tables\Columns\Layout\Stack; -use Filament\Tables\Columns\SpatieMediaLibraryImageColumn; -use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Enums\FiltersLayout; -use Filament\Tables\Filters\SelectFilter; +use Filament\Schemas\Schema; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Str; class CommunityResource extends Resource { protected static ?string $model = CommunityProfile::class; - protected static ?string $navigationIcon = 'heroicon-o-sun'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-sun'; protected static ?string $recordRouteKeyName = 'slug'; @@ -50,130 +36,16 @@ public static function getNavigationLabel(): string return __('navigation.community.network'); } - public static function infolist(Infolist $infolist): Infolist + public static function infolist(Schema $schema): Schema { - return $infolist - ->schema([ - Section::make() - ->schema([ - Grid::make() - ->extraAttributes([ - 'class' => 'items-center', - ]) - ->schema([ - TextEntry::make('description') - ->hiddenLabel() - ->size('sm') - ->html(), - - SpatieMediaLibraryImageEntry::make('logo') - ->hiddenLabel() - ->collection('logo') - ->conversion('large') - ->extraAttributes([ - 'class' => 'justify-center', - ]) - ->extraImgAttributes([ - 'class' => 'max-w-full max-h-24 md:max-h-48 p-4 ', - ]) - ->size('100%') - ->alignCenter(), - ]), - - InfolistSplit::make([ - TextEntry::make('website') - ->icon('heroicon-o-link') - ->hiddenLabel() - ->url(fn (?string $state) => $state) - ->openUrlInNewTab(), - - TextEntry::make('email') - ->icon('heroicon-o-envelope') - ->hiddenLabel() - ->url( - fn (?string $state) => $state !== null - ? "mailto:{$state}" - : null - ) - ->openUrlInNewTab(), - - TextEntry::make('phone') - ->icon('heroicon-o-phone') - ->hiddenLabel() - ->url( - fn (?string $state) => $state !== null - ? "tel:{$state}" - : null - ) - ->openUrlInNewTab(), - ]), - ]), - ]); + return CommunityResourceSchema::infolist($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing(fn (Builder $query) => $query->with('services', 'counties')) - ->columns([ - Split::make([ - Stack::make([ - TextColumn::make('counties.name') - ->size('sm') - ->color('gray'), - - TextColumn::make('name') - ->searchable() - ->size('text-3xl') - ->weight('normal') - ->extraAttributes([ - 'class' => '-mt-3.5', - ]), - - TextColumn::make('description') - ->size('text-sm line-clamp-4') - ->formatStateUsing( - fn (string $state) => Str::of($state) - ->stripTags() - ->limit(300, '...') - ), - - ServiceChipsColumn::make('services'), - ]) - ->extraAttributes([ - 'class' => 'flex flex-col gap-6', - ]) - ->columnSpan(2), - - SpatieMediaLibraryImageColumn::make('logo') - ->collection('logo') - ->conversion('large') - ->extraImgAttributes([ - 'class' => 'max-w-full max-h-24 md:max-h-48 p-4', - ]) - ->size('100%') - ->alignCenter(), - - ]) - ->from('md'), - ]) + return CommunityResourceSchema::table($table) ->contentGrid([ 'default' => 1, - ]) - ->filters([ - ServicesFilter::make('services') - ->label(__('organization.filter.service.label')) - ->columnSpanFull(), - - SelectFilter::make('county') - ->relationship('counties', 'name') - ->label(__('organization.filter.county.label')) - ->placeholder(__('organization.filter.county.placeholder')), - ]) - ->filtersLayout(FiltersLayout::AboveContent) - ->actions([ - Tables\Actions\ViewAction::make() - ->hidden(), ]); } @@ -187,8 +59,8 @@ public static function getRelations(): array public static function getPages(): array { return [ - 'index' => Pages\ListCommunityProfiles::route('/'), - 'view' => Pages\ViewCommunityProfile::route('/{record:slug}'), + 'index' => ListCommunityProfiles::route('/'), + 'view' => ViewCommunityProfile::route('/{record:slug}'), ]; } } diff --git a/app/Filament/Organizations/Resources/CommunityResource/Pages/ListCommunityProfiles.php b/app/Filament/Organizations/Resources/CommunityResource/Pages/ListCommunityProfiles.php index f60cb1c4..95cc8656 100644 --- a/app/Filament/Organizations/Resources/CommunityResource/Pages/ListCommunityProfiles.php +++ b/app/Filament/Organizations/Resources/CommunityResource/Pages/ListCommunityProfiles.php @@ -12,7 +12,7 @@ class ListCommunityProfiles extends ListRecords { protected static string $resource = CommunityResource::class; - protected static string $view = 'filament.organizations.pages.empty-page'; + protected string $view = 'filament.organizations.pages.empty-page'; public function getBreadcrumbs(): array { diff --git a/app/Filament/Organizations/Resources/DocumentResource.php b/app/Filament/Organizations/Resources/DocumentResource.php index 7ed4a7ef..a2d07c33 100644 --- a/app/Filament/Organizations/Resources/DocumentResource.php +++ b/app/Filament/Organizations/Resources/DocumentResource.php @@ -4,89 +4,12 @@ namespace App\Filament\Organizations\Resources; -use App\Enums\DocumentType; -use App\Forms\Components\Select; -use App\Models\Document; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Resources\Resource; -use Illuminate\Contracts\Support\Htmlable; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Number; - -class DocumentResource extends Resource +/** + * @deprecated This resource has been moved to BeneficiaryResource\Resources\DocumentResource + * Use App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource instead + */ +class DocumentResource extends \App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource { - protected static ?string $model = Document::class; - - protected static bool $shouldRegisterNavigation = false; - - public static string $parentResource = BeneficiaryResource::class; - - public static function getRecordTitle(Model|null $record): string|null|Htmlable - { - return $record->name; - } - - public static function form(Form $form): Form - { - return $form - ->schema(self::getSchema()); - } - - public static function getRelations(): array - { - return [ - // - ]; - } - - /** - * @return array - */ - public static function getSchema(): array - { - return [ - Select::make('type') - ->label(__('beneficiary.section.documents.labels.type')) - ->options(DocumentType::options()) - ->enum(DocumentType::class) - ->columnSpanFull() - ->required(), - - TextInput::make('name') - ->label(__('beneficiary.section.documents.labels.name')) - ->placeholder(__('beneficiary.placeholder.file_name')) - ->columnSpanFull() - ->maxLength(200) - ->required(), - - Textarea::make('observations') - ->placeholder(__('beneficiary.placeholder.observations')) - ->label(__('beneficiary.section.documents.labels.observations')) - ->columnSpanFull() - ->maxLength(500), - - SpatieMediaLibraryFileUpload::make('document_file') - ->label(__('beneficiary.section.documents.labels.document_file')) - ->openable() - ->downloadable() - ->acceptedFileTypes([ - 'application/pdf', - 'application/msword', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'text/csv', - 'application/vnd.ms-excel', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'image/*', - ]) - ->maxSize(config('media-library.max_file_size')) - ->helperText(__('beneficiary.helper_text.document_file', [ - 'size' => Number::fileSize(config('media-library.max_file_size')), - ])) - ->columnSpanFull() - ->required(), - ]; - } + // This class is kept for backward compatibility + // All functionality has been moved to BeneficiaryResource\Resources\DocumentResource } diff --git a/app/Filament/Organizations/Resources/DocumentResource/Pages/ListDocuments.php b/app/Filament/Organizations/Resources/DocumentResource/Pages/ListDocuments.php deleted file mode 100644 index 3d78c6d6..00000000 --- a/app/Filament/Organizations/Resources/DocumentResource/Pages/ListDocuments.php +++ /dev/null @@ -1,133 +0,0 @@ -disableLogging(); - } - - public function getBreadcrumbs(): array - { - return BeneficiaryBreadcrumb::make($this->parent) - ->getBreadcrumbs('documents.index'); - } - - public function getTitle(): string|Htmlable - { - return __('beneficiary.section.documents.title.page'); - } - - protected function getHeaderActions(): array - { - return [ - BackAction::make() - ->url(BeneficiaryResource::getUrl('view', ['record' => $this->parent])), - - Actions\CreateAction::make() - ->modalHeading(__('beneficiary.section.documents.title.add_modal')) - ->label(__('beneficiary.section.documents.actions.add')) - ->createAnother(false) - ->modalSubmitActionLabel(__('beneficiary.section.documents.actions.create')) - ->modalCancelActionLabel(__('general.action.cancel')) - ->mutateFormDataUsing(function (array $data) { - $data[$this->getParentRelationshipKey()] = $this->parent->id; - - return $data; - }) - ->relationship(null) - ->successRedirectUrl(fn (Document $record) => static::getParentResource()::getUrl('documents.view', [ - 'parent' => $this->parent, - 'record' => $record, - ])), - ]; - } - - public function table(Table $table): Table - { - return $table - ->modifyQueryUsing(fn (Builder $query) => $query->with('beneficiary')) - ->heading(__('beneficiary.section.documents.title.table')) - ->actionsColumnLabel(__('general.action.actions')) - ->columns([ - DateColumn::make('date') - ->label(__('beneficiary.section.documents.labels.date')) - ->sortable(), - - TextColumn::make('name') - ->label(__('beneficiary.section.documents.labels.name')), - - TextColumn::make('type') - ->label(__('beneficiary.section.documents.labels.type')) - ->sortable(), - - TextColumn::make('observations') - ->label(__('beneficiary.section.documents.labels.observations')) - ->sortable(), - ]) - ->actions([ - ViewAction::make('view') - ->label(__('general.action.view_details')) - ->color('primary') - ->url(fn (Document $record) => self::getParentResource()::getUrl('documents.view', [ - 'parent' => $this->parent, - 'record' => $record, - ])), - ]) - ->filters([ - SelectFilter::make('type') - ->label(__('beneficiary.section.documents.labels.type')) - ->options(DocumentType::options()) - ->searchable(), - ]) - ->emptyStateIcon('heroicon-o-document') - ->emptyStateHeading(__('beneficiary.helper_text.documents')) - ->emptyStateDescription(__('beneficiary.helper_text.documents_2')) - ->emptyStateActions([ - CreateAction::make() - ->modalHeading(__('beneficiary.section.documents.title.add_modal')) - ->label(__('beneficiary.section.documents.actions.add')) - ->createAnother(false) - ->outlined() - ->size(ActionSize::ExtraLarge) - ->modalSubmitActionLabel(__('beneficiary.section.documents.actions.create')) - ->modalCancelActionLabel(__('general.action.cancel')) - ->mutateFormDataUsing(function (array $data) { - $data[$this->getParentRelationshipKey()] = $this->parent->id; - - return $data; - }) - ->successRedirectUrl(fn (Document $record) => static::getParentResource()::getUrl('documents.view', [ - 'parent' => $this->parent, - 'record' => $record, - ])), - ]); - } -} diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource.php b/app/Filament/Organizations/Resources/InterventionPlanResource.php index bf31b75a..b69e2f07 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource.php @@ -20,7 +20,7 @@ class InterventionPlanResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static string $parentResource = BeneficiaryResource::class; + public static ?string $parentResource = BeneficiaryResource::class; public static function getPages(): array { diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/EditInterventionPlan.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/EditInterventionPlan.php index 4d6fe9c2..2cc9f231 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/EditInterventionPlan.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/EditInterventionPlan.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\InterventionPlanResource\Pages; +use Filament\Actions\DeleteAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Organizations\Resources\InterventionPlanResource; use Filament\Actions; @@ -18,7 +19,7 @@ class EditInterventionPlan extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + DeleteAction::make(), ]; } } diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ListInterventionPlans.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ListInterventionPlans.php index a36b3eaf..1a17d85a 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ListInterventionPlans.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ListInterventionPlans.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\InterventionPlanResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\InterventionPlanResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListInterventionPlans extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ViewInterventionPlan.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ViewInterventionPlan.php index ce089083..a8365c36 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ViewInterventionPlan.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Pages/ViewInterventionPlan.php @@ -4,6 +4,12 @@ namespace App\Filament\Organizations\Resources\InterventionPlanResource\Pages; +use Filament\Actions\EditAction; +use Filament\Schemas\Schema; +use App\Filament\Organizations\Resources\InterventionPlanResource\Widgets\ServicesWidget; +use App\Filament\Organizations\Resources\InterventionPlanResource\Widgets\BenefitsWidget; +use App\Filament\Organizations\Resources\InterventionPlanResource\Widgets\ResultsWidget; +use App\Filament\Organizations\Resources\InterventionPlanResource\Widgets\MonthlyPlanWidget; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -12,9 +18,9 @@ use App\Models\Beneficiary; use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Filament\Actions; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\TextInput; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -46,12 +52,12 @@ protected function getHeaderActions(): array BackAction::make() ->url(BeneficiaryResource::getUrl('view', ['record' => $this->parent])), - Actions\EditAction::make() + EditAction::make() ->label(__('intervention_plan.actions.edit_intervention_plan')) ->icon('heroicon-o-pencil') ->outlined() ->modal() - ->form([ + ->schema([ Grid::make() ->relationship('beneficiary') ->schema([ @@ -87,9 +93,9 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make(__('intervention_plan.headings.plan_details')) ->columns(3) ->schema([ @@ -117,7 +123,10 @@ public function infolist(Infolist $infolist): Infolist protected function getFooterWidgets(): array { return [ - InterventionPlanResource\Widgets\Interventions::class, + ServicesWidget::class, + BenefitsWidget::class, + ResultsWidget::class, + MonthlyPlanWidget::class, ]; } } diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/BenefitsWidget.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/BenefitsWidget.php index 23b8e489..34c2d3ab 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/BenefitsWidget.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/BenefitsWidget.php @@ -13,7 +13,7 @@ use Filament\Forms\Components\Hidden; use Filament\Forms\Components\RichEditor; use Filament\Forms\Components\TextInput; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Support\Enums\Alignment; use Filament\Tables\Actions\CreateAction; use Filament\Tables\Actions\DeleteAction; @@ -36,10 +36,10 @@ public function table(Table $table): Table ) ->heading(__('intervention_plan.headings.benefit_services')) ->headerActions([ - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('intervention_plan.actions.add_benefit')) ->modalHeading(__('intervention_plan.headings.add_benefit_modal')) - ->form($this->getBenefitSchema()) + ->schema($this->getBenefitSchema()) ->createAnother(false), ]) ->columns([ @@ -61,12 +61,12 @@ public function table(Table $table): Table ->label(__('intervention_plan.headings.benefit_description')) ->html(), ]) - ->actions([ + ->recordActions([ EditAction::make() - ->form($this->getBenefitSchema()) + ->schema($this->getBenefitSchema()) ->modalHeading(__('intervention_plan.headings.edit_benefit')) ->extraModalFooterActions([ - DeleteAction::make() + \Filament\Actions\DeleteAction::make() ->label(__('intervention_plan.actions.delete_benefit')) ->link() ->icon(null) diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/Interventions.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/Interventions.php deleted file mode 100644 index b719baa8..00000000 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/Interventions.php +++ /dev/null @@ -1,22 +0,0 @@ -heading(__('intervention_plan.headings.monthly_plans')) ->headerActions([ - Action::make('create_modal') + \Filament\Actions\Action::make('create_modal') ->label(__('intervention_plan.actions.create_monthly_plan')) ->modalHeading(__('intervention_plan.headings.create_monthly_plan_modal')) ->modalDescription(__('intervention_plan.labels.create_monthly_plan_modal')) ->modalSubmitAction( - Action::make('crete_from_last') + \Filament\Actions\Action::make('crete_from_last') ->label(__('intervention_plan.actions.create_monthly_plan_from_last')) ->url(InterventionPlanResource::getUrl('create_monthly_plan', [ 'parent' => $this->record, @@ -41,14 +41,14 @@ public function table(Table $table): Table ])) ) ->modalCancelAction( - Action::make('create_simple') + \Filament\Actions\Action::make('create_simple') ->label(__('intervention_plan.actions.create_monthly_plan_simple')) ->outlined() ->url(InterventionPlanResource::getUrl('create_monthly_plan', ['parent' => $this->record])) ) ->visible(fn () => $this->record->monthlyPlans->count()), - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('intervention_plan.actions.create_monthly_plan')) ->url(InterventionPlanResource::getUrl('create_monthly_plan', ['parent' => $this->record])) ->visible(fn () => ! $this->record->monthlyPlans->count()), @@ -66,8 +66,8 @@ public function table(Table $table): Table TextColumn::make('monthly_plan_interventions_count') ->label(__('intervention_plan.headings.interventions_count')), ]) - ->actions([ - ViewAction::make() + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_details')) ->url(fn (MonthlyPlan $record) => InterventionPlanResource::getUrl('view_monthly_plan', [ 'parent' => $this->record, diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ResultsWidget.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ResultsWidget.php index 66c9ce3f..5db7332f 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ResultsWidget.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ResultsWidget.php @@ -4,16 +4,17 @@ namespace App\Filament\Organizations\Resources\InterventionPlanResource\Widgets; +use Filament\Actions\CreateAction; use App\Forms\Components\DatePicker; use App\Forms\Components\Select; use App\Models\InterventionPlan; use App\Models\User; use App\Tables\Actions\EditAction; use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Support\Enums\Alignment; use Filament\Tables; use Filament\Tables\Actions\DeleteAction; @@ -35,10 +36,10 @@ public function table(Table $table): Table ) ->heading(__('intervention_plan.headings.results_table')) ->headerActions([ - Tables\Actions\CreateAction::make() + CreateAction::make() ->label(__('intervention_plan.actions.add_result')) ->createAnother(false) - ->form($this->getFormSchema()) + ->schema($this->getFormSchema()) ->modalHeading(__('intervention_plan.actions.add_result')), ]) ->columns([ @@ -73,12 +74,12 @@ public function table(Table $table): Table ->label(__('intervention_plan.headings.observations')) ->html(), ]) - ->actions([ + ->recordActions([ EditAction::make() - ->form($this->getFormSchema()) + ->schema($this->getFormSchema()) ->modalHeading(__('intervention_plan.headings.edit_result')) ->extraModalFooterActions([ - DeleteAction::make() + \Filament\Actions\DeleteAction::make() ->cancelParentActions() ->label(__('intervention_plan.actions.delete_result')) ->link() diff --git a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ServicesWidget.php b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ServicesWidget.php index 16bda484..5189bd2e 100644 --- a/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ServicesWidget.php +++ b/app/Filament/Organizations/Resources/InterventionPlanResource/Widgets/ServicesWidget.php @@ -12,8 +12,8 @@ use App\Models\OrganizationService; use App\Models\Specialist; use Filament\Facades\Filament; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\RichEditor; use Filament\Forms\Components\TextInput; @@ -51,14 +51,14 @@ public function table(Table $table): Table ->label(__('intervention_plan.labels.meetings_count')), ]) ->headerActions([ - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('intervention_plan.actions.add_service')) ->modalHeading(__('intervention_plan.headings.add_service')) - ->form(self::getServiceSchema($this->record)) + ->schema(self::getServiceSchema($this->record)) ->createAnother(false), ]) - ->actions([ - ViewAction::make() + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_details')) ->url(fn (InterventionService $record) => InterventionPlanResource::getUrl('view_intervention_service', [ 'parent' => $this->record, diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource.php b/app/Filament/Organizations/Resources/InterventionServiceResource.php index c3a28ce6..49631984 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources; +use App\Filament\Organizations\Resources\InterventionServiceResource\Pages\ListInterventionServices; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages\EditBeneficiaryIntervention; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages\ViewBeneficiaryIntervention; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource\Pages\ViewMeetings; @@ -18,12 +19,12 @@ class InterventionServiceResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static string $parentResource = InterventionPlanResource::class; + public static ?string $parentResource = InterventionPlanResource::class; public static function getPages(): array { return [ - 'index' => Pages\ListInterventionServices::route('/'), + 'index' => ListInterventionServices::route('/'), 'view_intervention' => ViewBeneficiaryIntervention::route('/{parent}/beneficiaryIntervention/{record}'), 'edit_intervention' => EditBeneficiaryIntervention::route('/{parent}/beneficiaryIntervention/{record}/edit'), 'view_meetings' => ViewMeetings::route('/{parent}/meetings/{record}'), diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditCounselingSheet.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditCounselingSheet.php index 96db8ad4..dc695ebf 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditCounselingSheet.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditCounselingSheet.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\InterventionServiceResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Enums\AllowancePerson; @@ -29,19 +30,19 @@ use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Awcodes\TableRepeater\Components\TableRepeater; use Awcodes\TableRepeater\Header; -use Filament\Forms\Components\Actions\Action; +use Filament\Actions\Action; use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Radio; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -84,7 +85,7 @@ protected function getHeaderActions(): array ]; } - public function form(Form $form): Form + public function form(Schema $form): Schema { $counselingSheet = $this->getRecord() ->organizationServiceWithoutStatusCondition @@ -98,7 +99,7 @@ public function form(Form $form): Form default => [], }; - return $form->schema([ + return $form->components([ Section::make() ->relationship('counselingSheet') ->schema($schema), @@ -291,7 +292,7 @@ public static function getSchemaForPsychologicalAssistance(): array ->hidden( fn (Get $get) => ! $get('data.physics') || ExtendedFrequency::isValue($get('data.physics'), ExtendedFrequency::NONE) || - ExtendedFrequency::isValue($get('data.physics'), ExtendedFrequency::NO_ANSWER) + ExtendedFrequency::isValue($get('data.physics'), ExtendedFrequency::NO_ANSWER) ) ->maxLength(1500), @@ -300,7 +301,7 @@ public static function getSchemaForPsychologicalAssistance(): array ->hidden( fn (Get $get) => ! $get('data.sexed') || ExtendedFrequency::isValue($get('data.sexed'), ExtendedFrequency::NONE) || - ExtendedFrequency::isValue($get('data.sexed'), ExtendedFrequency::NO_ANSWER) + ExtendedFrequency::isValue($get('data.sexed'), ExtendedFrequency::NO_ANSWER) ) ->maxLength(1500), @@ -429,7 +430,7 @@ public static function getSchemaForSocialAssistance(?InterventionService $interv }) ->columns() ->addAction( - fn (Action $action) => $action->link() + fn (\Filament\Actions\Action $action) => $action->link() ->label(__('intervention_plan.actions.add_social_relationship')) ) ->reorderable(false) @@ -490,7 +491,7 @@ public static function getSchemaForSocialAssistance(?InterventionService $interv }) ->columns() ->addAction( - fn (Action $action) => $action->link() + fn (\Filament\Actions\Action $action) => $action->link() ->label(__('intervention_plan.actions.add_social_relationship')) ) ->reorderable(false) @@ -564,7 +565,7 @@ public static function getSchemaForSocialAssistance(?InterventionService $interv Section::make(__('intervention_plan.headings.children_details')) ->visible(fn () => ! $interventionService || $interventionService?->beneficiary->children->count()) ->headerActions([ - Action::make('view_children_identity') + \Filament\Actions\Action::make('view_children_identity') ->label(__('intervention_plan.actions.view_children_identity')) ->icon('heroicon-o-arrow-top-right-on-square') ->url(fn () => BeneficiaryResource::getUrl('view_identity', [ @@ -598,7 +599,7 @@ public static function getSchemaForSocialAssistance(?InterventionService $interv ->hiddenLabel() ->deletable(false) ->reorderable(false) - ->addAction(fn (Action $action) => $action->hidden()) + ->addAction(fn (\Filament\Actions\Action $action) => $action->hidden()) ->schema([ Grid::make() ->columns(15) diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditInterventionService.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditInterventionService.php index 1e058894..11ba76ed 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditInterventionService.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/EditInterventionService.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\InterventionServiceResource\Pages; +use Filament\Actions\DeleteAction; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; @@ -13,7 +15,7 @@ use App\Filament\Organizations\Resources\InterventionServiceResource; use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Filament\Actions; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; @@ -52,7 +54,7 @@ protected function getHeaderActions(): array BackAction::make() ->url($this->getRedirectUrl()), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('intervention_plan.actions.delete_service')) ->icon('heroicon-o-trash') ->modalHeading(__('intervention_plan.actions.delete_service')) @@ -64,9 +66,9 @@ protected function getHeaderActions(): array ]; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') ->schema(ServicesWidget::getServiceSchema()), diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ListInterventionServices.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ListInterventionServices.php index 86a86f46..76b4296f 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ListInterventionServices.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ListInterventionServices.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\InterventionServiceResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\InterventionServiceResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListInterventionServices extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ViewInterventionService.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ViewInterventionService.php index 1b633078..c923cf57 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ViewInterventionService.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Pages/ViewInterventionService.php @@ -4,6 +4,9 @@ namespace App\Filament\Organizations\Resources\InterventionServiceResource\Pages; +use App\Filament\Organizations\Resources\InterventionServiceResource\Widgets\CounselingSheetWidget; +use App\Filament\Organizations\Resources\InterventionServiceResource\Widgets\InterventionsWidget; +use App\Filament\Organizations\Resources\InterventionServiceResource\Widgets\ServiceDescriptionWidget; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -45,7 +48,9 @@ protected function getHeaderActions(): array protected function getFooterWidgets(): array { return [ - InterventionServiceResource\Widgets\ServiceWidget::class, + CounselingSheetWidget::class, + InterventionsWidget::class, + ServiceDescriptionWidget::class, ]; } } diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/CounselingSheetWidget.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/CounselingSheetWidget.php index 85548ad8..77ff3b6c 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/CounselingSheetWidget.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/CounselingSheetWidget.php @@ -24,10 +24,10 @@ use App\Models\InterventionService; use App\Widgets\InfolistWidget; use Filament\Infolists\Components\Actions\Action; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Illuminate\Support\Str; @@ -401,7 +401,7 @@ public function getSchemaForSocialAssistance(): array ->visible(fn ($record) => $record->beneficiary->children->count()) ->compact() ->headerActions([ - Action::make('view_children_identity') + \Filament\Actions\Action::make('view_children_identity') ->label(__('intervention_plan.actions.view_children_identity')) ->icon('heroicon-o-arrow-top-right-on-square') ->url(fn ($record) => BeneficiaryResource::getUrl('view_identity', [ diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/InterventionsWidget.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/InterventionsWidget.php index 95b8b693..991a187b 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/InterventionsWidget.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/InterventionsWidget.php @@ -4,6 +4,8 @@ namespace App\Filament\Organizations\Resources\InterventionServiceResource\Widgets; +use Filament\Tables\Columns\TextColumn; +use Filament\Actions\ViewAction; use App\Filament\Organizations\Resources\BeneficiaryInterventionResource; use App\Filament\Organizations\Resources\InterventionServiceResource; use App\Models\BeneficiaryIntervention; @@ -26,31 +28,31 @@ public function table(Table $table): Table ->withCount('meetings')) ->heading(__('intervention_plan.headings.interventions')) ->columns([ - Tables\Columns\TextColumn::make('organizationServiceIntervention.serviceInterventionWithoutStatusCondition.name') + TextColumn::make('organizationServiceIntervention.serviceInterventionWithoutStatusCondition.name') ->label(__('intervention_plan.labels.intervention')), - Tables\Columns\TextColumn::make('specialist.name_role') + TextColumn::make('specialist.name_role') ->label(__('intervention_plan.labels.specialist')), - Tables\Columns\TextColumn::make('interval') + TextColumn::make('interval') ->label(__('intervention_plan.labels.interval')), - Tables\Columns\TextColumn::make('meetings_count') + TextColumn::make('meetings_count') ->label(__('intervention_plan.labels.meetings_count')), ]) ->headerActions([ - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('intervention_plan.actions.add_intervention')) ->createAnother(false) ->modalHeading(__('intervention_plan.headings.add_intervention', ['name' => $this->record->organizationServiceWithoutStatusCondition?->serviceWithoutStatusCondition->name])) - ->form([ + ->schema([ Hidden::make('intervention_service_id') ->default($this->record->id), ...BeneficiaryInterventionResource::getSchema($this->record->beneficiary, $this->record->organization_service_id), ]), ]) - ->actions([ - Tables\Actions\ViewAction::make() + ->recordActions([ + ViewAction::make() ->label(__('general.action.view_details')) ->url(fn (BeneficiaryIntervention $record) => InterventionServiceResource::getUrl('view_meetings', [ 'parent' => $this->record, diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceDescriptionWidget.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceDescriptionWidget.php index 783bca61..b3bbee61 100644 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceDescriptionWidget.php +++ b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceDescriptionWidget.php @@ -8,7 +8,7 @@ use App\Infolists\Components\Actions\EditAction; use App\Models\InterventionService; use App\Widgets\InfolistWidget; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; class ServiceDescriptionWidget extends InfolistWidget diff --git a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceWidget.php b/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceWidget.php deleted file mode 100644 index dec09911..00000000 --- a/app/Filament/Organizations/Resources/InterventionServiceResource/Widgets/ServiceWidget.php +++ /dev/null @@ -1,21 +0,0 @@ -relationship('monitorings') + ->inverseRelationship('beneficiary'); + } public static function getRecordTitle(Model|null $record): string|null|Htmlable { return $record->number; } + + public static function getPages(): array + { + return [ + 'index' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\ListMonitoring::route('/'), + 'create' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\CreateMonitoring::route('/create'), + 'view' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\ViewMonitoring::route('/{record}'), + 'edit_details' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\EditDetails::route('/{record}/editDetails'), + 'edit_children' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\EditChildren::route('/{record}/editChildren'), + 'edit_general' => \App\Filament\Organizations\Resources\MonitoringResource\Pages\EditGeneral::route('/{record}/editGeneral'), + ]; + } } diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/CreateMonitoring.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/CreateMonitoring.php index d3026933..26a6088a 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/CreateMonitoring.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/CreateMonitoring.php @@ -4,8 +4,8 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Schemas\Components\Wizard\Step; use App\Actions\BackAction; -use App\Concerns\HasParentResource; use App\Concerns\PreventMultipleSubmit; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -15,8 +15,8 @@ use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Carbon\Carbon; use Filament\Actions\Action; -use Filament\Forms\Components\Wizard; -use Filament\Forms\Set; +use Filament\Schemas\Components\Wizard; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\CreateRecord; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Illuminate\Contracts\Support\Htmlable; @@ -25,7 +25,6 @@ class CreateMonitoring extends CreateRecord { use HasWizard; - use HasParentResource; use PreventMultipleSubmit; use PreventSubmitFormOnEnter; @@ -40,9 +39,10 @@ class CreateMonitoring extends CreateRecord public function getBreadcrumbs(): array { $breadcrumb = __('monitoring.breadcrumbs.file', ['file_number' => null]); + $ownerRecord = $this->getOwnerRecord(); return array_merge( - BeneficiaryBreadcrumb::make($this->parent) + BeneficiaryBreadcrumb::make($ownerRecord) ->getBreadcrumbsForCreateMonitoring(), [$breadcrumb], ); @@ -55,8 +55,7 @@ public function getTitle(): string|Htmlable protected function getRedirectUrl(): string { - return static::getParentResource()::getUrl('monitorings.view', [ - 'parent' => $this->parent, + return MonitoringResource::getUrl('view', [ 'record' => $this->record, ]); } @@ -65,15 +64,16 @@ protected function getHeaderActions(): array { return [ BackAction::make() - ->url(BeneficiaryResource::getUrl('monitorings.index', ['parent' => $this->parent])), + ->url(MonitoringResource::getUrl('index')), ]; } protected function afterFill(): void { $copyLastFile = (bool) request('copyLastFile'); - $this->lastFile = self::getParent() - ?->monitoring + $ownerRecord = $this->getOwnerRecord(); + $this->lastFile = $ownerRecord + ->monitorings ->sortByDesc('id') ->first() ?->loadMissing(['children', 'specialistsTeam']); @@ -99,17 +99,17 @@ public function getSteps(): array { return [ - Wizard\Step::make(__('monitoring.headings.details')) + Step::make(__('monitoring.headings.details')) ->schema(EditDetails::getSchema()) ->afterStateHydrated(fn (Set $set) => $set('specialistsTeam', $this->specialistTeam)), - Wizard\Step::make(__('monitoring.headings.child_info')) + Step::make(__('monitoring.headings.child_info')) ->schema(EditChildren::getSchema()) ->afterStateHydrated(function (Set $set) { $set('children', $this->children); }), - Wizard\Step::make(__('monitoring.headings.general')) + Step::make(__('monitoring.headings.general')) ->schema(EditGeneral::getSchema()), ]; @@ -127,29 +127,33 @@ protected function getCancelFormAction(): Action { return Action::make('cancel') ->label(__('filament-panels::resources/pages/create-record.form.actions.cancel.label')) - ->alpineClickHandler('document.referrer ? window.history.back() : (window.location.href = ' . Js::from($this->previousUrl ?? static::getParentResource()::getUrl('monitorings.index', ['parent' => $this->parent])) . ')') + ->alpineClickHandler('document.referrer ? window.history.back() : (window.location.href = ' . Js::from($this->previousUrl ?? MonitoringResource::getUrl('index')) . ')') ->color('gray'); } protected function mutateFormDataBeforeCreate(array $data): array { // Set the parent relationship key to the parent resource's ID. - $data[$this->getParentRelationshipKey()] = $this->parent->id; + $data['beneficiary_id'] = $this->getOwnerRecord()->id; return $data; } private function getChildren(): array { + $ownerRecord = $this->getOwnerRecord(); + if ($this->lastFile && $this->lastFile->children->isNotEmpty()) { return $this->lastFile->children->toArray(); } - return $this->parent->children->toArray(); + return $ownerRecord->children->toArray(); } private function getSpecialists(): array { + $ownerRecord = $this->getOwnerRecord(); + if ($this->lastFile && $this->lastFile->specialistsTeam->isNotEmpty()) { return $this->lastFile ->specialistsTeam @@ -157,7 +161,7 @@ private function getSpecialists(): array ->toArray(); } - return $this->parent + return $ownerRecord ->specialistsTeam ?->filter(fn (Specialist $specialist) => $specialist->role_id) ->each( diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditChildren.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditChildren.php index ffdad695..dfd7aa9f 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditChildren.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditChildren.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToMonitoring; @@ -14,13 +15,13 @@ use App\Forms\Components\Repeater; use App\Forms\Components\Select; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -48,15 +49,15 @@ protected function getTabSlug(): string return Str::slug(__('monitoring.headings.child_info')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') - ->schema(self::getSchema())]); + ->schema($this->getFormSchema())]); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Placeholder::make('empty_state_children') diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditDetails.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditDetails.php index fd976c72..446330a7 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditDetails.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditDetails.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToMonitoring; @@ -15,13 +16,13 @@ use App\Models\UserRole; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Awcodes\TableRepeater\Header; -use Filament\Forms\Components\Grid; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Str; @@ -49,16 +50,16 @@ protected function getTabSlug(): string return Str::slug(__('monitoring.headings.details')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') - ->schema(self::getSchema()), + ->schema($this->getFormSchema()), ]); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Grid::make() diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditGeneral.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditGeneral.php index 4fdd1776..b17e018c 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditGeneral.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/EditGeneral.php @@ -4,16 +4,17 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Schemas\Schema; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; use App\Concerns\RedirectToMonitoring; use App\Filament\Organizations\Resources\MonitoringResource; use App\Forms\Components\DatePicker; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; @@ -44,16 +45,16 @@ protected function getTabSlug(): string return Str::slug(__('monitoring.headings.general')); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make() ->maxWidth('3xl') - ->schema(self::getSchema()), + ->schema($this->getFormSchema()), ]); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Group::make() diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/ListMonitoring.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/ListMonitoring.php index 322ad59b..ccc3644f 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/ListMonitoring.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/ListMonitoring.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Actions\Action; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -43,13 +44,13 @@ protected function getHeaderActions(): array BackAction::make() ->url(BeneficiaryResource::getUrl('view', ['record' => $this->parent])), - Actions\Action::make('open_modal') + Action::make('open_modal') ->label(__('monitoring.actions.create')) ->visible(fn () => $this->parent->monitoring->count()) ->modalHeading(__('monitoring.headings.modal_create')) ->modalDescription(__('monitoring.labels.modal_create_description')) ->modalSubmitAction( - Actions\Action::make('crete_from_last') + Action::make('crete_from_last') ->label(__('monitoring.actions.create_from_last')) ->url( fn () => self::getParentResource()::getUrl('monitorings.create', [ @@ -59,7 +60,7 @@ protected function getHeaderActions(): array ) ) ->modalCancelAction( - Actions\Action::make('create_simple') + Action::make('create_simple') ->label(__('monitoring.actions.create_simple')) ->url( fn () => self::getParentResource()::getUrl('monitorings.create', [ @@ -103,8 +104,8 @@ public function table(Table $table): Table ->sortable() ->listWithLineBreaks(), ]) - ->actions([ - ViewAction::make() + ->recordActions([ + \Filament\Actions\ViewAction::make() ->label(__('general.action.view_details')) ->color('primary') ->url(fn (Monitoring $record) => (static::getParentResource()::getUrl('monitorings.view', [ @@ -112,7 +113,7 @@ public function table(Table $table): Table 'record' => $record, ]))), ]) - ->actionsColumnLabel(__('monitoring.headings.actions')) + ->recordActionsColumnLabel(__('monitoring.headings.actions')) ->modifyQueryUsing( fn (Builder $query) => $query->with([ 'specialistsTeam.user', @@ -124,7 +125,7 @@ public function table(Table $table): Table ->emptyStateDescription(__('monitoring.labels.empty_state_table')) ->emptyStateIcon('heroicon-o-document') ->emptyStateActions([ - CreateAction::make() + \Filament\Actions\CreateAction::make() ->label(__('monitoring.actions.create')) ->url( fn () => self::getParentResource()::getUrl('monitorings.create', [ diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Pages/ViewMonitoring.php b/app/Filament/Organizations/Resources/MonitoringResource/Pages/ViewMonitoring.php index 3627878e..279525ee 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Pages/ViewMonitoring.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Pages/ViewMonitoring.php @@ -4,6 +4,10 @@ namespace App\Filament\Organizations\Resources\MonitoringResource\Pages; +use Filament\Actions\DeleteAction; +use Filament\Schemas\Schema; +use Filament\Schemas\Components\Tabs\Tab; +use Filament\Support\Enums\TextSize; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -14,11 +18,11 @@ use App\Infolists\Components\SectionHeader; use App\Services\Breadcrumb\BeneficiaryBreadcrumb; use Filament\Actions; -use Filament\Infolists\Components\Grid; -use Filament\Infolists\Components\Group; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Group; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -47,7 +51,7 @@ protected function getHeaderActions(): array BackAction::make() ->url(BeneficiaryResource::getUrl('monitorings.index', ['parent' => $this->parent])), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('monitoring.actions.delete')) ->outlined() ->icon('heroicon-o-trash') @@ -59,14 +63,14 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Tabs::make() ->columnSpanFull() ->persistTabInQueryString() ->schema([ - Tabs\Tab::make(__('monitoring.headings.details')) + Tab::make(__('monitoring.headings.details')) ->maxWidth('3xl') ->schema([ Section::make(__('monitoring.headings.details')) @@ -97,14 +101,14 @@ public function infolist(Infolist $infolist): Infolist ]), ]), - Tabs\Tab::make(__('beneficiary.section.identity.tab.beneficiary')) + Tab::make(__('beneficiary.section.identity.tab.beneficiary')) ->maxWidth('3xl') ->schema([ Group::make() ->relationship('beneficiary') ->schema(ViewBeneficiaryIdentity::identitySchemaForOtherPage($this->parent))]), - Tabs\Tab::make(__('monitoring.headings.child_info')) + Tab::make(__('monitoring.headings.child_info')) ->maxWidth('3xl') ->schema([ Section::make(__('monitoring.headings.child_info')) @@ -160,7 +164,7 @@ public function infolist(Infolist $infolist): Infolist ]), ]), - Tabs\Tab::make(__('monitoring.headings.general')) + Tab::make(__('monitoring.headings.general')) ->maxWidth('3xl') ->schema([ Section::make(__('monitoring.headings.general')) @@ -189,7 +193,7 @@ public function infolist(Infolist $infolist): Infolist TextEntry::make('progress_placeholder') ->hiddenLabel() ->default(__('monitoring.headings.progress')) - ->size(TextEntry\TextEntrySize::Medium), + ->size(TextSize::Medium), TextEntry::make('progress') ->label(__('monitoring.labels.progress')), @@ -197,7 +201,7 @@ public function infolist(Infolist $infolist): Infolist TextEntry::make('progress_placeholder') ->hiddenLabel() ->default(__('monitoring.headings.observation')) - ->size(TextEntry\TextEntrySize::Medium), + ->size(TextSize::Medium), TextEntry::make('observation') ->label(__('monitoring.labels.observation')), @@ -225,7 +229,7 @@ private function getGeneralMonitoringDataFields(): array $formFields[] = TextEntry::make('progress_placeholder') ->hiddenLabel() ->default(__(\sprintf('monitoring.headings.%s', $field))) - ->size(TextEntry\TextEntrySize::Medium); + ->size(TextSize::Medium); $formFields[] = TextEntry::make($field . '.objection') ->label(__('monitoring.labels.objection')); @@ -240,7 +244,7 @@ private function getGeneralMonitoringDataFields(): array return $formFields; } - protected function configureDeleteAction(Actions\DeleteAction $action): void + protected function configureDeleteAction(DeleteAction $action): void { $resource = static::getResource(); diff --git a/app/Filament/Organizations/Resources/MonitoringResource/Widgets/MonitoringWidget.php b/app/Filament/Organizations/Resources/MonitoringResource/Widgets/MonitoringWidget.php index 19b504f1..f252462d 100644 --- a/app/Filament/Organizations/Resources/MonitoringResource/Widgets/MonitoringWidget.php +++ b/app/Filament/Organizations/Resources/MonitoringResource/Widgets/MonitoringWidget.php @@ -29,7 +29,7 @@ public function table(Table $table): Table ->paginated(false) ->heading(__('monitoring.headings.widget_table')) ->headerActions([ - Action::make('view_monitoring') + \Filament\Actions\Action::make('view_monitoring') ->label(__('general.action.view_details')) ->link() ->visible(fn () => $this->record->monitoring->count()) @@ -45,7 +45,7 @@ public function table(Table $table): Table ]) ->emptyStateHeading(__('monitoring.headings.widget_empty_state')) ->emptyStateActions([ - Action::make('create_monitoring') + \Filament\Actions\Action::make('create_monitoring') ->label(__('monitoring.actions.create_widget')) ->outlined() ->url(BeneficiaryResource::getUrl('monitorings.create', ['parent' => $this->record])), diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource.php b/app/Filament/Organizations/Resources/MonthlyPlanResource.php index 211cfde7..3a18f6ee 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource.php @@ -4,6 +4,9 @@ namespace App\Filament\Organizations\Resources; +use App\Filament\Organizations\Resources\MonthlyPlanResource\Pages\ListMonthlyPlans; +use App\Filament\Organizations\Resources\MonthlyPlanResource\Pages\CreateMonthlyPlan; +use App\Filament\Organizations\Resources\MonthlyPlanResource\Pages\EditMonthlyPlanDetails; use App\Filament\Organizations\Resources\MonthlyPlanResource\Pages; use App\Models\MonthlyPlan; use Filament\Resources\Resource; @@ -14,14 +17,14 @@ class MonthlyPlanResource extends Resource protected static bool $shouldRegisterNavigation = false; - public static string $parentResource = InterventionPlanResource::class; + public static ?string $parentResource = InterventionPlanResource::class; public static function getPages(): array { return [ - 'index' => Pages\ListMonthlyPlans::route('/'), - 'create' => Pages\CreateMonthlyPlan::route('/create'), - 'edit' => Pages\EditMonthlyPlanDetails::route('/{record}/edit'), + 'index' => ListMonthlyPlans::route('/'), + 'create' => CreateMonthlyPlan::route('/create'), + 'edit' => EditMonthlyPlanDetails::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/CreateMonthlyPlan.php b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/CreateMonthlyPlan.php index 42e5b4cd..551c20f6 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/CreateMonthlyPlan.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/CreateMonthlyPlan.php @@ -13,9 +13,9 @@ use App\Filament\Organizations\Resources\MonthlyPlanResource; use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Filament\Facades\Filament; -use Filament\Forms\Components\Wizard\Step; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Components\Wizard\Step; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\Pages\CreateRecord; use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard; use Illuminate\Contracts\Support\Htmlable; diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanDetails.php b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanDetails.php index 246e3f5e..9803887c 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanDetails.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanDetails.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonthlyPlanResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; @@ -14,7 +15,7 @@ use App\Models\Beneficiary; use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; use Illuminate\Support\Str; @@ -59,12 +60,12 @@ public function getHeaderActions(): array ]; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema(self::getSchema($this->parent->beneficiary)); + return $schema->components($this->getFormSchema($this->parent->beneficiary)); } - public static function getSchema(?Beneficiary $beneficiary = null): array + protected function getFormSchema(?Beneficiary $beneficiary = null): array { return [ Section::make() diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanServicesAndInterventions.php b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanServicesAndInterventions.php index 35ba387c..9218c12a 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanServicesAndInterventions.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/EditMonthlyPlanServicesAndInterventions.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonthlyPlanResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Concerns\PreventSubmitFormOnEnter; @@ -18,15 +19,15 @@ use App\Services\Breadcrumb\InterventionPlanBreadcrumb; use Awcodes\TableRepeater\Header; use Filament\Facades\Filament; -use Filament\Forms\Components\Actions\Action; -use Filament\Forms\Components\Grid; +use Filament\Actions\Action; +use Filament\Schemas\Components\Grid; use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; -use Filament\Forms\Get; +use Filament\Schemas\Components\Utilities\Get; use Filament\Resources\Pages\EditRecord; use Filament\Support\Enums\Alignment; use Illuminate\Support\Str; @@ -71,15 +72,15 @@ public function getHeaderActions(): array ]; } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form->schema([ + return $schema->components([ Section::make(__('intervention_plan.headings.services_and_interventions')) - ->schema($this->getSchema()), + ->schema($this->getFormSchema()), ]); } - public static function getSchema(): array + protected function getFormSchema(): array { return [ Repeater::make('monthlyPlanServices') @@ -93,7 +94,7 @@ public static function getSchema(): array ]); }) ->addAction( - fn (Action $action) => $action + fn (\Filament\Actions\Action $action) => $action ->link() ->label(__('intervention_plan.actions.add_service_repeater')) ->color('primary') diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ListMonthlyPlans.php b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ListMonthlyPlans.php index 39b7b4cb..4848aa40 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ListMonthlyPlans.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ListMonthlyPlans.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonthlyPlanResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\MonthlyPlanResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -15,7 +16,7 @@ class ListMonthlyPlans extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make(), + CreateAction::make(), ]; } } diff --git a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ViewMonthlyPlan.php b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ViewMonthlyPlan.php index aa24c27c..b86b128f 100644 --- a/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ViewMonthlyPlan.php +++ b/app/Filament/Organizations/Resources/MonthlyPlanResource/Pages/ViewMonthlyPlan.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\MonthlyPlanResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Concerns\HasParentResource; use App\Filament\Organizations\Resources\BeneficiaryResource; @@ -17,9 +18,9 @@ use Carbon\Carbon; use Filament\Actions\DeleteAction; use Filament\Infolists\Components\RepeatableEntry; -use Filament\Infolists\Components\Section; -use Filament\Infolists\Components\Tabs; -use Filament\Infolists\Components\Tabs\Tab; +use Filament\Schemas\Components\Section; +use Filament\Schemas\Components\Tabs; +use Filament\Schemas\Components\Tabs\Tab; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -66,7 +67,7 @@ public function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { $this->getRecord() ->loadMissing([ @@ -74,7 +75,7 @@ public function infolist(Infolist $infolist): Infolist 'monthlyPlanServices.monthlyPlanInterventions.serviceIntervention', ]); - return $infolist->schema([ + return $schema->components([ Tabs::make() ->persistTabInQueryString() ->schema([ diff --git a/app/Filament/Organizations/Resources/ServiceResource.php b/app/Filament/Organizations/Resources/ServiceResource.php index 6dc8fdb2..f6b7281e 100644 --- a/app/Filament/Organizations/Resources/ServiceResource.php +++ b/app/Filament/Organizations/Resources/ServiceResource.php @@ -4,38 +4,21 @@ namespace App\Filament\Organizations\Resources; -use App\Enums\CounselingSheet; -use App\Filament\Organizations\Resources\InterventionServiceResource\Pages\EditCounselingSheet; -use App\Filament\Organizations\Resources\ServiceResource\Pages; -use App\Forms\Components\Notice; -use App\Forms\Components\Select; -use App\Forms\Components\TableRepeater; -use App\Models\InterventionService; +use App\Filament\Organizations\Schemas\ServiceResourceSchema; +use App\Filament\Organizations\Resources\ServiceResource\Pages\ListServices; +use App\Filament\Organizations\Resources\ServiceResource\Pages\CreateService; +use App\Filament\Organizations\Resources\ServiceResource\Pages\ViewService; +use App\Filament\Organizations\Resources\ServiceResource\Pages\EditService; use App\Models\OrganizationService; -use App\Models\Service; -use App\Models\ServiceIntervention; -use Awcodes\TableRepeater\Header; -use Filament\Actions\StaticAction; -use Filament\Forms; -use Filament\Forms\Components\Actions\Action; -use Filament\Forms\Components\Checkbox; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Form; -use Filament\Forms\Set; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables; -use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; class ServiceResource extends Resource { protected static ?string $model = OrganizationService::class; - protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-rectangle-stack'; protected static ?int $navigationSort = 32; @@ -49,223 +32,38 @@ public static function getNavigationLabel(): string return __('service.headings.navigation'); } - public static function form(Form $form): Form + public static function getModelLabel(): string { - return $form - ->schema([ - Forms\Components\Section::make() - ->maxWidth('3xl') - ->schema([ - Placeholder::make('before_form') - ->hiddenLabel() - ->content(__('service.helper_texts.before_form')), - - Select::make('service_id') - ->label(__('service.labels.name')) - ->visible(fn (string $operation) => $operation === 'create') - ->relationship( - 'service', - 'name', - fn (Builder $query, $state) => $query->whereNotIn( - 'id', - OrganizationService::query() - ->whereNot('service_id', $state) - ->pluck('service_id') - ) - ) - ->afterStateUpdated(self::populateTable()) - ->live() - ->required(), - - Placeholder::make('service') - ->label(__('service.labels.name')) - ->content(fn ($record) => $record->serviceWithoutStatusCondition->name) - ->visible(fn (string $operation) => $operation === 'edit'), - - Notice::make('counseling_sheet_placeholder') - ->content(function (Forms\Get $get) { - $service = Service::find($get('service_id')); - - return $service?->counseling_sheet ? __('service.helper_texts.counseling_sheet') : null; - }) - ->icon('heroicon-o-document-text') - ->key('counseling_sheet_placeholder') - ->visible(fn (Forms\Get $get) => Service::find($get('service_id')) - ?->counseling_sheet) - ->registerActions([ - Action::make('view_counseling_sheet') - ->label(__('service.actions.view_counseling_sheet')) - ->modalHeading( - fn (Forms\Get $get) => Service::find($get('service_id')) - ?->counseling_sheet - ?->getLabel() - ) - ->form(function (Forms\Get $get) { - $service = Service::find($get('service_id')); - - $counselingSheet = $service?->counseling_sheet; - - if (! $counselingSheet) { - return null; - } - - if (CounselingSheet::isValue($counselingSheet, CounselingSheet::LEGAL_ASSISTANCE)) { - return EditCounselingSheet::getLegalAssistanceForm(); - } - - if (CounselingSheet::isValue($counselingSheet, CounselingSheet::PSYCHOLOGICAL_ASSISTANCE)) { - return EditCounselingSheet::getSchemaForPsychologicalAssistance(); - } - - return []; - }) - ->disabledForm() - ->modalAutofocus(false) - ->modalSubmitAction(fn (StaticAction $action) => $action->hidden()) - ->link(), - ]), - - Group::make() - ->visible(fn (Forms\Get $get) => $get('service_id')) - ->schema([ - Placeholder::make('counseling_sheet') - ->label(__('service.headings.interventions')) - ->content(__('service.helper_texts.interventions')), - - TableRepeater::make('interventions') - ->helperText(__('service.helper_texts.under_interventions_table')) - ->relationship('interventions') - ->addAction(fn (Action $action) => $action->hidden()) - ->deletable(false) - ->reorderable(false) - ->mutateRelationshipDataBeforeCreateUsing(function (array $data) { - unset($data['active']); - - return $data; - }) - ->headers([ - Header::make('active') - ->label(__('service.labels.select')), - - Header::make('name') - ->label(__('service.labels.interventions')), - - Header::make('status') - ->label(__('service.labels.status')), - - ]) - ->schema([ - Checkbox::make('active') - ->label(__('service.labels.select')) - ->afterStateUpdated(fn (bool $state, Set $set) => $state ? $set('status', true) : $set('status', false)) - ->live(), - - Placeholder::make('name') - ->label(__('service.labels.interventions')) - ->hiddenLabel() - ->content(fn ($state) => $state), - - Toggle::make('status') - ->label(__('service.labels.status')) - ->disabled(fn (Forms\Get $get) => ! $get('active')), - - Hidden::make('id'), - - Hidden::make('service_intervention_id'), - ]) - ->afterStateHydrated(self::populateTable()), - ]), - ]), - ]); + return __('service.label.singular'); } - public static function populateTable(): \Closure + public static function getPluralModelLabel(): string { - return function (Set $set, Forms\Get $get) { - $serviceID = $get('service_id'); - $interventions = ServiceIntervention::query() - ->where('service_id', $serviceID) - ->with('organizationIntervention') - ->active() - ->get(); - - $interventions->map(function (ServiceIntervention $intervention) { - $intervention->service_intervention_id = $intervention->id; - $intervention->id = $intervention->organizationIntervention?->id; - $intervention->status = $intervention->organizationIntervention?->status ?? false; - $intervention->active = isset($intervention->organizationIntervention) ?: false; - }); + return __('service.label.plural'); + } - $set('interventions', $interventions->toArray()); - }; + public static function form(Schema $schema): Schema + { + return ServiceResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing( - fn (Builder $query) => $query - ->with(['serviceWithoutStatusCondition', 'interventionServices.beneficiary']) - ->withCount(['interventions']) - ) - ->columns([ - TextColumn::make('serviceWithoutStatusCondition.name') - ->label(__('service.labels.name')), - - TextColumn::make('interventions_count') - ->label(__('service.labels.interventions')), - - TextColumn::make('beneficiary') - ->label(__('service.labels.cases')) - ->default( - fn (OrganizationService $record) => $record->interventionServices - ->map(fn (InterventionService $item) => $item->beneficiary) - ->unique() - ->count() - ), - - TextColumn::make('status') - ->label(__('service.labels.status')), - ]) - ->filters([ - // - ]) - ->actions([ - Tables\Actions\ViewAction::make() - ->label(__('general.action.view_details')), - ]) - ->heading(__('service.headings.list_table')) - ->headerActions([ - Tables\Actions\CreateAction::make() - ->label(__('service.actions.create')), - ]) - ->emptyStateIcon('heroicon-o-clipboard-document-check') - ->emptyStateHeading(__('service.headings.empty_state_table')) - ->emptyStateDescription(''); + return ServiceResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListServices::route('/'), - 'create' => Pages\CreateService::route('/create'), - 'view' => Pages\ViewService::route('/{record}'), - 'edit' => Pages\EditService::route('/{record}/edit'), + 'index' => ListServices::route('/'), + 'create' => CreateService::route('/create'), + 'view' => ViewService::route('/{record}'), + 'edit' => EditService::route('/{record}/edit'), ]; } public static function processInterventionsBeforeSave(?array $interventions): ?array { - foreach ($interventions as $key => &$intervention) { - if (! $intervention['active']) { - unset($interventions[$key]); - continue; - } - - unset($intervention['active']); - $intervention['status'] = (bool) $intervention['status']; - } - - return $interventions; + return ServiceResourceSchema::processInterventionsBeforeSave($interventions); } } diff --git a/app/Filament/Organizations/Resources/ServiceResource/Pages/EditService.php b/app/Filament/Organizations/Resources/ServiceResource/Pages/EditService.php index 162098f1..ff84c1c3 100644 --- a/app/Filament/Organizations/Resources/ServiceResource/Pages/EditService.php +++ b/app/Filament/Organizations/Resources/ServiceResource/Pages/EditService.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\ServiceResource\Pages; +use Filament\Actions\DeleteAction; use App\Actions\BackAction; use App\Concerns\PreventSubmitFormOnEnter; use App\Filament\Organizations\Resources\ServiceResource; @@ -45,7 +46,7 @@ protected function getHeaderActions(): array ChangeStatusAction::make() ->disabled(fn () => ! $this->getRecord()->service), - Actions\DeleteAction::make() + DeleteAction::make() ->label(__('service.actions.delete')) ->icon('heroicon-s-trash') ->outlined() diff --git a/app/Filament/Organizations/Resources/ServiceResource/Pages/ViewService.php b/app/Filament/Organizations/Resources/ServiceResource/Pages/ViewService.php index e302d3ac..f34f73b8 100644 --- a/app/Filament/Organizations/Resources/ServiceResource/Pages/ViewService.php +++ b/app/Filament/Organizations/Resources/ServiceResource/Pages/ViewService.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\ServiceResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Enums\CounselingSheet; use App\Filament\Organizations\Resources\InterventionServiceResource\Pages\EditCounselingSheet; @@ -14,7 +15,7 @@ use Filament\Actions\EditAction; use Filament\Actions\StaticAction; use Filament\Infolists\Components\Actions\Action; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -48,7 +49,7 @@ protected function getHeaderActions(): array ]; } - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { $this->getRecord() ->loadMissing([ @@ -56,7 +57,7 @@ public function infolist(Infolist $infolist): Infolist 'interventions.beneficiaryInterventions.interventionPlan', ]); - return $infolist->schema([ + return $schema->components([ Section::make() ->visible(fn () => $this->getRecord()->serviceWithoutStatusCondition->counseling_sheet) ->maxWidth('3xl') @@ -65,7 +66,7 @@ public function infolist(Infolist $infolist): Infolist ->state(__('service.helper_texts.counseling_sheet')) ->icon('heroicon-o-document-text') ->action( - Action::make('view_counseling_sheet') + \Filament\Actions\Action::make('view_counseling_sheet') ->label(__('service.actions.view_counseling_sheet')) ->modalHeading( $this->getRecord() @@ -73,7 +74,7 @@ public function infolist(Infolist $infolist): Infolist ->counseling_sheet ?->getLabel() ) - ->form(function () { + ->schema(function () { $counselingSheet = $this->getRecord()->serviceWithoutStatusCondition->counseling_sheet; if (CounselingSheet::isValue($counselingSheet, CounselingSheet::LEGAL_ASSISTANCE)) { @@ -91,7 +92,7 @@ public function infolist(Infolist $infolist): Infolist return []; }) ->disabledForm() - ->modalSubmitAction(fn (StaticAction $action) => $action->hidden()) + ->modalSubmitAction(fn (\Filament\Actions\Action $action) => $action->hidden()) ->link() ->modalAutofocus(false), ), diff --git a/app/Filament/Organizations/Resources/UserResource.php b/app/Filament/Organizations/Resources/UserResource.php index b3016c43..9aa7171a 100644 --- a/app/Filament/Organizations/Resources/UserResource.php +++ b/app/Filament/Organizations/Resources/UserResource.php @@ -4,38 +4,21 @@ namespace App\Filament\Organizations\Resources; -use App\Enums\AdminPermission; -use App\Enums\CasePermission; -use App\Filament\Organizations\Resources\UserResource\Pages; -use App\Forms\Components\Select; -use App\Models\OrganizationUserPermissions; -use App\Models\Role; +use App\Filament\Organizations\Schemas\UserResourceSchema; +use App\Filament\Organizations\Resources\UserResource\Pages\ListUsers; +use App\Filament\Organizations\Resources\UserResource\Pages\CreateUser; +use App\Filament\Organizations\Resources\UserResource\Pages\ViewUser; +use App\Filament\Organizations\Resources\UserResource\Pages\EditUser; use App\Models\User; -use App\Tables\Columns\DateTimeColumn; -use Filament\Facades\Filament; -use Filament\Forms\Components\CheckboxList; -use Filament\Forms\Components\Group; -use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Placeholder; -use Filament\Forms\Components\Section; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; -use Filament\Forms\Get; -use Filament\Forms\Set; +use Filament\Schemas\Schema; use Filament\Resources\Resource; -use Filament\Tables; -use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Facades\Cache; -use Illuminate\Support\HtmlString; -use Illuminate\Validation\Rules\Unique; class UserResource extends Resource { protected static ?string $model = User::class; - protected static ?string $navigationIcon = 'heroicon-o-users'; + protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-users'; protected static ?string $tenantOwnershipRelationshipName = 'organizations'; @@ -61,228 +44,24 @@ public static function getPluralModelLabel(): string return __('user.specialist_label.plural'); } - public static function form(Form $form): Form + public static function form(Schema $schema): Schema { - return $form - ->schema(self::getSchema()); + return UserResourceSchema::form($schema); } public static function table(Table $table): Table { - return $table - ->modifyQueryUsing(fn (Builder $query) => $query->with(['rolesInOrganization', 'userStatus'])) - ->heading(__('user.heading.table')) - ->columns([ - TextColumn::make('first_name') - ->sortable() - ->label(__('user.labels.first_name')) - ->searchable(), - - TextColumn::make('last_name') - ->label(__('user.labels.last_name')) - ->searchable(), - - TextColumn::make('rolesInOrganization.name') - ->sortable() - ->label(__('user.labels.roles')), - - TextColumn::make('userStatus.status') - ->sortable() - ->label(__('user.labels.account_status')) - ->suffix(fn (User $record) => $record->isNgoAdmin() ? '**' : ''), - - DateTimeColumn::make('last_login_at') - ->sortable() - ->label(__('user.labels.last_login_at')), - ]) - ->actions([ - Tables\Actions\ViewAction::make() - ->label(__('general.action.view_details')), - ]); + return UserResourceSchema::table($table); } public static function getPages(): array { return [ - 'index' => Pages\ListUsers::route('/'), - 'create' => Pages\CreateUser::route('/create'), - 'view' => Pages\ViewUser::route('/{record}'), - 'edit' => Pages\EditUser::route('/{record}/edit'), + 'index' => ListUsers::route('/'), + 'create' => CreateUser::route('/create'), + 'view' => ViewUser::route('/{record}'), + 'edit' => EditUser::route('/{record}/edit'), ]; } - /** - * @return array - */ - public static function getSchema(): array - { - return [ - Section::make() - ->columns() - ->maxWidth('3xl') - ->visible(fn (string $operation) => $operation === 'edit') - ->schema([ - Placeholder::make('userStatus.status') - ->content(fn (User $record, $state) => $record->userStatus->status->getLabel()), - - Placeholder::make('last_login_at') - ->label(__('user.labels.last_login_at_date_time')) - ->content( - fn (User $record) => $record->last_login_at && $record->last_login_at !== '-' ? - $record->last_login_at->format('d.m.Y H:i:s') : - '-' - ), - ]), - - Section::make() - ->columns() - ->maxWidth('3xl') - ->schema([ - TextInput::make('first_name') - ->label(__('user.labels.first_name')) - ->required(), - - TextInput::make('last_name') - ->label(__('user.labels.last_name')) - ->required(), - - TextInput::make('email') - ->label(__('user.labels.email')) - ->email() - ->unique( - ignoreRecord: true, - modifyRuleUsing: fn (Unique $rule, string $operation) => $operation === 'edit' ? $rule : - $rule->whereIn('id', User::getTenantOrganizationUsers()->keys()) - ) - ->required(), - - TextInput::make('phone_number') - ->label(__('user.labels.phone_number')) - ->tel() - ->maxLength(14) - ->required(), - - Select::make('role_id') - ->label(__('user.labels.select_roles')) - ->relationship('rolesInOrganization', 'name') - ->options(Role::active()->pluck('name', 'id')) - ->preload() - ->multiple() - ->live() - ->required() - ->afterStateHydrated(self::setDefaultCaseAndNgoAdminPermissions()) - ->afterStateUpdated(self::setDefaultCaseAndNgoAdminPermissions()), - - Placeholder::make('obs') - ->hiddenLabel() - ->visible(fn (Get $get) => $get('role_id')) - ->content(function (Get $get) { - foreach ($get('role_id') as $roleID) { - $role = self::getRole($roleID); - if ($role->case_permissions->contains(CasePermission::HAS_ACCESS_TO_ALL_CASES)) { - return new HtmlString(__('user.placeholders.user_role_with_permissions_for_all_cases')); - } - } - - return new HtmlString(__('user.placeholders.user_role_without_permissions_for_all_cases')); - }) - ->columnSpanFull(), - - Group::make() - ->relationship('permissions') - ->columnSpanFull() - ->schema([ - CheckboxList::make('case_permissions') - ->label(__('user.labels.case_permissions')) - ->options(CasePermission::getOptionsWithoutCaseManager()) - ->disableOptionWhen(function (Get $get, string $value, ?OrganizationUserPermissions $record) { - if ($record?->user->isNgoAdmin()) { - return true; - } - - foreach ($get('../role_id') as $roleID) { - $role = self::getRole($roleID); - - $permission = $role->case_permissions - ->filter(fn ($item) => CasePermission::isValue($value, $item)); - if ($permission->count()) { - return true; - } - } - - return false; - }) - ->columnSpanFull(), - - CheckboxList::make('admin_permissions') - ->label(__('user.labels.admin_permissions')) - ->options(AdminPermission::options()) - ->disableOptionWhen(function (Get $get, string $value, ?OrganizationUserPermissions $record) { - if ($record?->user->isNgoAdmin()) { - return true; - } - - foreach ($get('../role_id') as $roleID) { - $role = self::getRole($roleID); - - $permission = $role->ngo_admin_permissions - ->filter(fn ($item) => AdminPermission::isValue($value, $item)); - if ($permission->count()) { - return true; - } - } - - return false; - }) - ->columnSpanFull(), - - Hidden::make('organization_id') - ->default(Filament::getTenant()->id), - ]), - ]), - ]; - } - - public static function setDefaultCaseAndNgoAdminPermissions(): \Closure - { - return function (Set $set, Get $get, $state, ?User $record) { - $casePermissions = $get('permissions.case_permissions') ?: []; - $adminPermissions = $get('permissions.admin_permissions') ?: []; - - if ($record?->isNgoAdmin()) { - $casePermissions = CasePermission::values(); - $adminPermissions = AdminPermission::values(); - - $set('permissions.case_permissions', $casePermissions); - $set('permissions.admin_permissions', $adminPermissions); - - return; - } - - foreach ($state as $roleID) { - $role = self::getRole($roleID); - $defaultCasePermissions = $role->case_permissions?->map(fn ($item) => $item->value)->toArray(); - $defaultNgoAdminPermissions = $role->ngo_admin_permissions?->map(fn ($item) => $item->value)->toArray(); - - $casePermissions = array_merge($casePermissions, $defaultCasePermissions); - $adminPermissions = array_merge($adminPermissions, $defaultNgoAdminPermissions); - } - $casePermissions = array_unique($casePermissions); - $adminPermissions = array_unique($adminPermissions); - sort($casePermissions); - sort($adminPermissions); - - $set('permissions.case_permissions', $casePermissions); - $set('permissions.admin_permissions', $adminPermissions); - }; - } - - protected static function getRole(mixed $roleID) - { - return Cache::driver('array') - ->rememberForever( - 'role_' . $roleID, - fn () => Role::find($roleID) - ); - } } diff --git a/app/Filament/Organizations/Resources/UserResource/Actions/ResetPasswordAction.php b/app/Filament/Organizations/Resources/UserResource/Actions/ResetPasswordAction.php index 10fab1af..f8f172e0 100644 --- a/app/Filament/Organizations/Resources/UserResource/Actions/ResetPasswordAction.php +++ b/app/Filament/Organizations/Resources/UserResource/Actions/ResetPasswordAction.php @@ -49,7 +49,7 @@ function (CanResetPassword $user, string $token): void { throw new Exception("Model [{$userClass}] does not have a [notify()] method."); } - $notification = new ResetPasswordNotification($token); + $notification = new \Filament\Auth\Notifications\ResetPassword($token); $notification->url = Filament::getResetPasswordUrl($token, $user); $user->notify($notification); diff --git a/app/Filament/Organizations/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Organizations/Resources/UserResource/Pages/ListUsers.php index 98498edb..485e86ce 100644 --- a/app/Filament/Organizations/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Organizations/Resources/UserResource/Pages/ListUsers.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\UserResource\Pages; +use Filament\Actions\CreateAction; use App\Filament\Organizations\Resources\UserResource; use Filament\Actions; use Filament\Resources\Pages\ListRecords; @@ -19,7 +20,7 @@ class ListUsers extends ListRecords protected function getHeaderActions(): array { return [ - Actions\CreateAction::make() + CreateAction::make() ->label(__('user.actions.add_specialist')), ]; } diff --git a/app/Filament/Organizations/Resources/UserResource/Pages/ViewUser.php b/app/Filament/Organizations/Resources/UserResource/Pages/ViewUser.php index 5979ed82..b382ff48 100644 --- a/app/Filament/Organizations/Resources/UserResource/Pages/ViewUser.php +++ b/app/Filament/Organizations/Resources/UserResource/Pages/ViewUser.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Resources\UserResource\Pages; +use Filament\Schemas\Schema; use App\Actions\BackAction; use App\Enums\AdminPermission; use App\Enums\CasePermission; @@ -17,8 +18,8 @@ use App\Infolists\Components\DateTimeEntry; use App\Infolists\Components\SectionHeader; use App\Models\User; -use Filament\Infolists\Components\Group; -use Filament\Infolists\Components\Section; +use Filament\Schemas\Components\Group; +use Filament\Schemas\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; use Filament\Resources\Pages\ViewRecord; @@ -27,9 +28,9 @@ class ViewUser extends ViewRecord { protected static string $resource = UserResource::class; - public function infolist(Infolist $infolist): Infolist + public function infolist(Schema $schema): Schema { - return $infolist->schema([ + return $schema->components([ Section::make() ->columns() ->maxWidth('3xl') diff --git a/app/Filament/Organizations/Schemas/BeneficiaryInterventionResourceSchema.php b/app/Filament/Organizations/Schemas/BeneficiaryInterventionResourceSchema.php new file mode 100644 index 00000000..417cde5b --- /dev/null +++ b/app/Filament/Organizations/Schemas/BeneficiaryInterventionResourceSchema.php @@ -0,0 +1,138 @@ +components([ + Section::make() + ->maxWidth('3xl') + ->columns() + ->schema(self::getFormComponents()), + ]); + } + + public static function getFormComponents(?Beneficiary $beneficiary = null, ?int $organizationServiceID = null): array + { + return [ + Group::make() + ->schema([ + Select::make('organization_service_intervention_id') + ->label(__('intervention_plan.labels.intervention_type')) + ->relationship('organizationServiceIntervention', 'name') + ->options(function (?BeneficiaryIntervention $record) use ($organizationServiceID) { + $organizationServiceID = $record?->interventionService->organization_service_id ?? $organizationServiceID; + + return OrganizationServiceIntervention::with('serviceIntervention') + ->where('organization_service_id', $organizationServiceID) + ->active() + ->get() + ->filter( + fn (OrganizationServiceIntervention $organizationServiceIntervention) => $organizationServiceIntervention->serviceIntervention + ) + ->pluck('serviceIntervention.name', 'id'); + }) + ->required(), + + Select::make('specialist_id') + ->label(__('intervention_plan.labels.responsible_specialist')) + ->options(function (?BeneficiaryIntervention $record) use ($beneficiary) { + $beneficiary = $beneficiary ?? $record?->beneficiary; + + return $beneficiary + ->specialistsTeam + ->loadMissing([ + 'user:id,first_name,last_name', + 'role:id,name', + ]) + ->pluck('name_role', 'id'); + }), + ]), + + Grid::make() + ->schema([ + DatePicker::make('start_date_interval') + ->label(__('intervention_plan.labels.start_date_interval')), + + DatePicker::make('end_date_interval') + ->label(__('intervention_plan.labels.end_date_interval')), + ]), + + Section::make(__('intervention_plan.headings.intervention_indicators')) + ->collapsible(fn ($operation) => $operation != 'edit') + ->collapsed(fn ($operation) => $operation != 'edit') + ->compact() + ->schema([ + Textarea::make('objections') + ->label(__('intervention_plan.labels.objections')) + ->maxLength(7000) + ->columnSpanFull(), + + Textarea::make('expected_results') + ->label(__('intervention_plan.labels.expected_results')) + ->maxLength(1000) + ->columnSpanFull(), + + Textarea::make('procedure') + ->label(__('intervention_plan.labels.procedure')) + ->maxLength(1000) + ->columnSpanFull(), + + Textarea::make('indicators') + ->label(__('intervention_plan.labels.indicators')) + ->maxLength(1000) + ->columnSpanFull(), + + Textarea::make('achievement_degree') + ->label(__('intervention_plan.labels.achievement_degree')) + ->maxLength(1000) + ->columnSpanFull(), + ]), + ]; + } + + public static function table(Table $table): Table + { + return $table + ->columns([]) + ->filters([]) + ->recordActions(self::getTableActions()) + ->toolbarActions(self::getToolbarActions()); + } + + public static function getTableActions(): array + { + return [ + EditAction::make(), + ]; + } + + public static function getToolbarActions(): array + { + return [ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]; + } +} diff --git a/app/Filament/Organizations/Schemas/BeneficiaryResource/InitialEvaluationSchema.php b/app/Filament/Organizations/Schemas/BeneficiaryResource/InitialEvaluationSchema.php new file mode 100644 index 00000000..4a338479 --- /dev/null +++ b/app/Filament/Organizations/Schemas/BeneficiaryResource/InitialEvaluationSchema.php @@ -0,0 +1,372 @@ +relationship('evaluateDetails') + ->maxWidth('3xl') + ->columns() + ->schema([ + DatePicker::make('registered_date') + ->label(__('beneficiary.section.initial_evaluation.labels.registered_date')) + ->required(), + + TextInput::make('file_number') + ->label(__('beneficiary.section.initial_evaluation.labels.file_number')) + ->placeholder(__('beneficiary.placeholder.file_number')) + ->maxLength(50), + + Select::make('specialist_id') + ->label(__('beneficiary.section.initial_evaluation.labels.specialist')) + ->placeholder(__('beneficiary.placeholder.specialist')) + ->required() + ->default(auth()->user()->id) + ->options(fn ($record) => User::getTenantOrganizationUsers()), + + Textarea::make('method_of_identifying_the_service') + ->label(__('beneficiary.section.initial_evaluation.labels.method_of_identifying_the_service')) + ->placeholder(__('beneficiary.placeholder.method_of_identifying_the_service')) + ->columnSpanFull() + ->maxLength(2000), + ]), + ]; + } + + public static function getEvaluationDetailsInfolistComponents(): array + { + return [ + Group::make() + ->columns() + ->relationship('evaluateDetails') + ->schema([ + DateEntry::make('registered_date') + ->label(__('beneficiary.section.initial_evaluation.labels.registered_date')), + + TextEntry::make('file_number') + ->label(__('beneficiary.section.initial_evaluation.labels.file_number')) + ->placeholder(__('beneficiary.placeholder.file_number')), + + TextEntry::make('specialist.full_name') + ->label(__('beneficiary.section.initial_evaluation.labels.specialist')) + ->placeholder(__('beneficiary.placeholder.specialist')), + + TextEntry::make('method_of_identifying_the_service') + ->label(__('beneficiary.section.initial_evaluation.labels.method_of_identifying_the_service')) + ->placeholder(__('beneficiary.placeholder.method_of_identifying_the_service')) + ->columnSpanFull(), + ]), + ]; + } + + public static function getRiskFactorsFormComponents(): array + { + return [ + Group::make() + ->relationship('riskFactors') + ->schema([ + Section::make(__('beneficiary.section.initial_evaluation.heading.violence_history')) + ->schema(self::getViolenceHistorySchema()), + Section::make(__('beneficiary.section.initial_evaluation.heading.violences_types')) + ->schema(self::getViolencesTypesSchema()), + Section::make(__('beneficiary.section.initial_evaluation.heading.risk_factors')) + ->schema(self::getRiskFactorsSchema()), + Section::make(__('beneficiary.section.initial_evaluation.heading.victim_perception_of_the_risk')) + ->schema(self::getVictimPerceptionOfTheRiskSchema()), + Section::make(__('beneficiary.section.initial_evaluation.heading.aggravating_factors')) + ->schema(self::getAggravatingFactorsSchema()), + Section::make(__('beneficiary.section.initial_evaluation.heading.social_support')) + ->columns() + ->schema(self::getSocialSupportSchema()), + ]), + ]; + } + + public static function getViolenceFormComponents(): array + { + return [ + Section::make() + ->relationship('violence') + ->maxWidth('3xl') + ->columns() + ->schema([ + Select::make('violence_types') + ->label(__('beneficiary.section.initial_evaluation.labels.violence_type')) + ->placeholder(__('beneficiary.placeholder.violence_type')) + ->options(Violence::options()) + ->multiple() + ->required(), + + Select::make('violence_primary_type') + ->label(__('beneficiary.section.initial_evaluation.labels.violence_primary_type')) + ->placeholder(__('beneficiary.placeholder.violence_primary_type')) + ->options(Violence::options()) + ->required(), + + Select::make('frequency_violence') + ->label(__('beneficiary.section.initial_evaluation.labels.frequency_violence')) + ->placeholder(__('beneficiary.placeholder.frequency_violence')) + ->options(Frequency::options()) + ->required(), + + RichEditor::make('description') + ->label(__('beneficiary.section.initial_evaluation.labels.description')) + ->placeholder(__('beneficiary.placeholder.description')) + ->helperText(__('beneficiary.helper_text.violence_description')) + ->columnSpanFull() + ->maxLength(5000), + ]), + ]; + } + + public static function getViolenceInfolistComponents(): array + { + return [ + Group::make() + ->relationship('violence') + ->columns() + ->schema([ + TextEntry::make('violence_types') + ->label(__('beneficiary.section.initial_evaluation.labels.violence_type')), + + EnumEntry::make('violence_primary_type') + ->label(__('beneficiary.section.initial_evaluation.labels.violence_primary_type')) + ->placeholder(__('beneficiary.placeholder.violence_primary_type')), + + EnumEntry::make('frequency_violence') + ->label(__('beneficiary.section.initial_evaluation.labels.frequency_violence')) + ->placeholder(__('beneficiary.placeholder.frequency_violence')), + + TextEntry::make('description') + ->label(__('beneficiary.section.initial_evaluation.labels.description')) + ->placeholder(__('beneficiary.placeholder.description')) + ->columnSpanFull() + ->html(), + ]), + ]; + } + + public static function getRequestedServicesFormComponents(): array + { + return [ + Group::make() + ->relationship('requestedServices') + ->schema([ + Section::make(__('beneficiary.section.initial_evaluation.heading.types_of_requested_services')) + ->schema(self::getRequestedServicesSchema()), + ]), + ]; + } + + public static function getRequestedServicesSchema(): array + { + return [ + CheckboxList::make('requested_services') + ->hiddenLabel() + ->options(RecommendationService::options()), + + Textarea::make('other_services_description') + ->hiddenLabel() + ->placeholder(__('beneficiary.placeholder.other_services')) + ->maxLength(100), + ]; + } + + public static function getBeneficiarySituationFormComponents(): array + { + return [ + Section::make() + ->relationship('beneficiarySituation') + ->maxWidth('3xl') + ->schema([ + TextInput::make('moment_of_evaluation') + ->label(__('beneficiary.section.initial_evaluation.labels.moment_of_evaluation')) + ->placeholder(__('beneficiary.placeholder.moment_of_evaluation')) + ->maxLength(100), + + RichEditor::make('description_of_situation') + ->label(__('beneficiary.section.initial_evaluation.labels.description_of_situation')) + ->placeholder(__('beneficiary.placeholder.description_of_situation')) + ->maxLength(5000), + ]), + ]; + } + + public static function getBeneficiarySituationInfolistComponents(): array + { + return [ + Group::make() + ->relationship('beneficiarySituation') + ->schema([ + TextEntry::make('moment_of_evaluation') + ->label(__('beneficiary.section.initial_evaluation.labels.moment_of_evaluation')), + + TextEntry::make('description_of_situation') + ->label(__('beneficiary.section.initial_evaluation.labels.description_of_situation')) + ->html(), + ]), + ]; + } + + public static function getViolenceHistorySchema(): array + { + $enumOptions = ViolenceHistorySchema::options(); + return self::getSchemaFromEnum($enumOptions); + } + + public static function getViolencesTypesSchema(): array + { + $enumOptions = ViolencesTypesSchema::options(); + return self::getSchemaFromEnum($enumOptions); + } + + public static function getRiskFactorsSchema(): array + { + $enumOptions = RiskFactorsSchema::options(); + return self::getSchemaFromEnum($enumOptions); + } + + public static function getVictimPerceptionOfTheRiskSchema(): array + { + $enumOptions = VictimPerceptionOfTheRiskSchema::options(); + return self::getSchemaFromEnum($enumOptions); + } + + public static function getAggravatingFactorsSchema(): array + { + $enumOptions = AggravatingFactorsSchema::options(); + return self::getSchemaFromEnum($enumOptions); + } + + public static function getSocialSupportSchema(): array + { + return [ + Group::make() + ->schema([ + Select::make('extended_family_can_provide') + ->label(__('beneficiary.section.initial_evaluation.labels.extended_family_can_provide')) + ->multiple() + ->options(Helps::options()) + ->disabled(fn (\Filament\Schemas\Components\Utilities\Get $get) => $get('extended_family_can_not_provide')), + + Checkbox::make('extended_family_can_not_provide') + ->label(__('beneficiary.section.initial_evaluation.labels.extended_family_can_not_provide')) + ->afterStateUpdated( + function ($state, \Filament\Schemas\Components\Utilities\Get $get, \Filament\Schemas\Components\Utilities\Set $set) { + if ($state) { + $set('extended_family_can_provide_old_values', $get('extended_family_can_provide')); + $set('extended_family_can_provide', null); + return; + } + $set('extended_family_can_provide', $get('extended_family_can_provide_old_values')); + } + ) + ->live(), + + Hidden::make('extended_family_can_provide_old_values'), + ]), + + Group::make() + ->schema([ + Select::make('friends_can_provide') + ->label(__('beneficiary.section.initial_evaluation.labels.friends_can_provide')) + ->multiple() + ->options(Helps::options()) + ->disabled(fn (\Filament\Schemas\Components\Utilities\Get $get) => $get('friends_can_not_provide')), + + Checkbox::make('friends_can_not_provide') + ->label(__('beneficiary.section.initial_evaluation.labels.friends_can_not_provide')) + ->afterStateUpdated( + function ($state, \Filament\Schemas\Components\Utilities\Get $get, \Filament\Schemas\Components\Utilities\Set $set) { + if ($state) { + $set('friends_can_provide_old_values', $get('friends_can_provide')); + $set('friends_can_provide', null); + return; + } + $set('friends_can_provide', $get('friends_can_provide_old_values')); + } + ) + ->live(), + + Hidden::make('friends_can_provide_old_values'), + ]), + ]; + } + + public static function getSchemaFromEnum(array $enumOptions): array + { + $fields = []; + foreach ($enumOptions as $key => $value) { + $fields[] = Radio::make('risk_factors.' . $key . '.value') + ->label($value) + ->inline() + ->inlineLabel(false) + ->options(Ternary::options()) + ->enum(Ternary::class); + $fields[] = TextInput::make('risk_factors.' . $key . '.description') + ->hiddenLabel() + ->placeholder(__('beneficiary.placeholder.observations')) + ->maxLength(100); + } + return $fields; + } + + public static function getInfolistSchemaFromEnum(array $enumOptions): array + { + $fields = []; + foreach ($enumOptions as $key => $value) { + $fields[] = TextEntry::make('risk_factors.' . $key . '.value') + ->label($value) + ->formatStateUsing(function ($record, $state) use ($key) { + $result = $state !== '-' + ? Ternary::tryFrom((int) $state)?->label() + : null; + + $result ??= '-'; + + $description = data_get($record->riskFactors->risk_factors, "{$key}.description"); + + if (filled($description)) { + $result .= " ({$description})"; + } + + return $result; + }) + ->inlineLabel(false); + } + return $fields; + } +} diff --git a/app/Filament/Organizations/Schemas/BeneficiaryResourceSchema.php b/app/Filament/Organizations/Schemas/BeneficiaryResourceSchema.php new file mode 100644 index 00000000..1ecdaed2 --- /dev/null +++ b/app/Filament/Organizations/Schemas/BeneficiaryResourceSchema.php @@ -0,0 +1,125 @@ +components([]); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing(function (Builder $query) { + return $query + ->with([ + 'managerTeam', + 'lastMonitoring', + // used for permissions + 'specialistsMembers', + ]) + ->whereUserHasAccess(); + }) + ->columns(self::getTableColumns()) + ->recordActions(self::getTableActions()) + ->filters(self::getTableFilters()) + ->paginationPageOptions([10, 20, 40, 60, 80, 100]) + ->defaultPaginationPageOption(20) + ->defaultSort('id', 'desc'); + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('id') + ->label(__('field.case_id')) + ->sortable() + ->searchable(true, fn (Builder $query, $search) => $query->where('beneficiaries.id', 'LIKE', '%' . $search . '%')), + + TextColumn::make('full_name') + ->label(__('field.beneficiary')) + ->description(fn ($record) => $record->initial_id ? __('beneficiary.labels.reactivated') : '') + ->sortable() + ->searchable(true, fn (Builder $query, $search) => $query->where('beneficiaries.full_name', 'LIKE', '%' . $search . '%')), + + TextColumn::make('created_at') + ->label(__('field.open_at')) + ->date() + ->toggleable() + ->sortable(), + + TextColumn::make('lastMonitoring.date') + ->label(__('field.last_evaluated_at')) + ->date() + ->toggleable(), + + TextColumn::make('managerTeam.user.full_name') + ->label(__('beneficiary.labels.case_manager')) + ->toggleable() + ->formatStateUsing( + fn ($state) => collect(explode(',', $state)) + ->map(fn ($item) => trim($item)) + ->unique() + ->join(', ') + ), + + TextColumn::make('status') + ->label(__('field.status')) + ->badge(), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->label(__('general.action.view_details')), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('status') + ->label(__('field.status')) + ->options(CaseStatus::options()) + ->modifyQueryUsing(fn (Builder $query, $state) => $state['value'] ? $query->where('beneficiaries.status', $state) : $query), + + SelectFilter::make('case_manager') + ->label(__('beneficiary.labels.case_manager')) + ->searchable() + ->preload() + ->relationship('managerTeam.user', 'full_name'), + + DateFilter::make('created_at') + ->label(__('field.open_at')) + ->attribute('beneficiaries.created_at'), + + DateFilter::make('monitorings.date') + ->label(__('field.last_evaluated_at')) + ->modifyQueryUsing( + fn (Builder $query, array $state) => $query + ->when(data_get($state, 'date_from'), function (Builder $query, string $date) { + $query->whereHas('lastMonitoring', fn (Builder $query) => $query->whereDate('date', '>=', $date)); + }) + ->when(data_get($state, 'date_until'), function (Builder $query, string $date) { + $query->whereHas('lastMonitoring', fn (Builder $query) => $query->whereDate('date', '<=', $date)); + }) + ), + ]; + } +} diff --git a/app/Filament/Organizations/Schemas/CommunityProfileResourceSchema.php b/app/Filament/Organizations/Schemas/CommunityProfileResourceSchema.php new file mode 100644 index 00000000..3070b171 --- /dev/null +++ b/app/Filament/Organizations/Schemas/CommunityProfileResourceSchema.php @@ -0,0 +1,120 @@ +components([ + Section::make() + ->columns(4) + ->schema(self::getFormComponents($services)), + ]); + } + + public static function getFormComponents($services): array + { + return [ + Group::make() + ->columnSpan(3) + ->schema([ + TextInput::make('name') + ->label(__('community.field.name')) + ->placeholder(__('community.placeholder.name')) + ->maxLength(200) + ->required(), + + Repeater::make('services') + ->relationship() + ->reorderable(false) + ->addActionLabel(__('service.action.create')) + ->minItems(1) + ->schema([ + Hidden::make('model_type') + ->default(app(CommunityProfile::class)->getMorphClass()), + + Select::make('service_id') + ->label(__('community.field.service')) + ->options($services) + ->required() + ->columnSpan(2), + + Toggle::make('is_visible') + ->label(__('community.field.service_visible')), + + Toggle::make('is_available') + ->label(__('community.field.service_available')), + + ]) + ->columns(4) + ->itemLabel(fn (array $state): ?string => $services[$state['service_id']] ?? null) + ->collapsible(), + + Select::make('counties') + ->relationship('counties', 'name') + ->label(__('community.field.location')) + ->placeholder(__('community.placeholder.location')) + ->multiple() + ->preload(), + ]), + + RichEditor::make('description') + ->label(__('community.field.description')) + ->placeholder(__('community.placeholder.description')) + ->toolbarButtons([ + 'bold', + 'bulletList', + 'italic', + 'link', + 'orderedList', + 'redo', + 'strike', + 'underline', + 'undo', + ]) + ->columnSpanFull(), + + SpatieMediaLibraryFileUpload::make('logo') + ->label(__('community.field.logo')) + ->helperText(__('community.help.logo')) + ->image() + ->collection('logo') + ->conversion('large') + ->columnSpanFull(), + + TextInput::make('email') + ->label(__('community.field.email')) + ->placeholder(__('placeholder.email')) + ->email(), + + TextInput::make('phone') + ->label(__('community.field.phone')) + ->placeholder(__('placeholder.phone')) + ->tel(), + + TextInput::make('website') + ->label(__('community.field.website')) + ->placeholder(__('placeholder.url')) + ->url(), + ]; + } +} diff --git a/app/Filament/Organizations/Schemas/CommunityResourceSchema.php b/app/Filament/Organizations/Schemas/CommunityResourceSchema.php new file mode 100644 index 00000000..38e26032 --- /dev/null +++ b/app/Filament/Organizations/Schemas/CommunityResourceSchema.php @@ -0,0 +1,166 @@ +components([ + Section::make() + ->schema([ + Grid::make() + ->extraAttributes([ + 'class' => 'items-center', + ]) + ->schema([ + TextEntry::make('description') + ->hiddenLabel() + ->size('sm') + ->html(), + + SpatieMediaLibraryImageEntry::make('logo') + ->hiddenLabel() + ->collection('logo') + ->conversion('large') + ->extraAttributes([ + 'class' => 'justify-center', + ]) + ->extraImgAttributes([ + 'class' => 'max-w-full max-h-24 md:max-h-48 p-4 ', + ]) + ->size('100%') + ->alignCenter(), + ]), + + Flex::make([ + TextEntry::make('website') + ->icon('heroicon-o-link') + ->hiddenLabel() + ->url(fn (?string $state) => $state) + ->openUrlInNewTab(), + + TextEntry::make('email') + ->icon('heroicon-o-envelope') + ->hiddenLabel() + ->url( + fn (?string $state) => $state !== null + ? "mailto:{$state}" + : null + ) + ->openUrlInNewTab(), + + TextEntry::make('phone') + ->icon('heroicon-o-phone') + ->hiddenLabel() + ->url( + fn (?string $state) => $state !== null + ? "tel:{$state}" + : null + ) + ->openUrlInNewTab(), + ]), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing(fn (Builder $query) => $query->with('services', 'counties')) + ->columns(self::getTableColumns()) + ->filters(self::getTableFilters()) + ->filtersLayout(FiltersLayout::AboveContent) + ->recordActions(self::getTableActions()); + } + + public static function getTableColumns(): array + { + return [ + Split::make([ + Stack::make([ + TextColumn::make('counties.name') + ->size('sm') + ->color('gray'), + + TextColumn::make('name') + ->searchable() + ->size('text-3xl') + ->weight('normal') + ->extraAttributes([ + 'class' => '-mt-3.5', + ]), + + TextColumn::make('description') + ->size('text-sm line-clamp-4') + ->formatStateUsing( + fn (string $state) => Str::of($state) + ->stripTags() + ->limit(300, '...') + ), + + ServiceChipsColumn::make('services'), + ]) + ->extraAttributes([ + 'class' => 'flex flex-col gap-6', + ]) + ->columnSpan(2), + + SpatieMediaLibraryImageColumn::make('logo') + ->collection('logo') + ->conversion('large') + ->extraImgAttributes([ + 'class' => 'max-w-full max-h-24 md:max-h-48 p-4', + ]) + ->size('100%') + ->alignCenter(), + + ]) + ->from('md'), + ]; + } + + public static function getTableFilters(): array + { + return [ + ServicesFilter::make('services') + ->label(__('organization.filter.service.label')) + ->columnSpanFull(), + + SelectFilter::make('county') + ->relationship('counties', 'name') + ->label(__('organization.filter.county.label')) + ->placeholder(__('organization.filter.county.placeholder')), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->hidden(), + ]; + } +} diff --git a/app/Filament/Organizations/Schemas/DocumentResourceSchema.php b/app/Filament/Organizations/Schemas/DocumentResourceSchema.php new file mode 100644 index 00000000..dae13d87 --- /dev/null +++ b/app/Filament/Organizations/Schemas/DocumentResourceSchema.php @@ -0,0 +1,128 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing(fn (Builder $query) => $query->with('beneficiary')) + ->heading(__('beneficiary.section.documents.title.table')) + ->recordActionsColumnLabel(__('general.action.actions')) + ->columns(self::getTableColumns()) + ->recordActions(self::getTableActions()) + ->filters(self::getTableFilters()) + ->emptyStateIcon('heroicon-o-document') + ->emptyStateHeading(__('beneficiary.helper_text.documents')) + ->emptyStateDescription(__('beneficiary.helper_text.documents_2')); + } + + public static function getTableColumns(): array + { + return [ + DateColumn::make('date') + ->label(__('beneficiary.section.documents.labels.date')) + ->sortable(), + + TextColumn::make('name') + ->label(__('beneficiary.section.documents.labels.name')), + + TextColumn::make('type') + ->label(__('beneficiary.section.documents.labels.type')) + ->sortable(), + + TextColumn::make('observations') + ->label(__('beneficiary.section.documents.labels.observations')) + ->sortable(), + ]; + } + + public static function getTableActions(): array + { + return [ + \Filament\Actions\ViewAction::make('view') + ->label(__('general.action.view_details')) + ->color('primary') + ->url(fn ($record) => \App\Filament\Organizations\Resources\BeneficiaryResource\Resources\DocumentResource::getUrl('view', [ + 'beneficiary' => $record->beneficiary, + 'record' => $record, + ])), + ]; + } + + public static function getTableFilters(): array + { + return [ + SelectFilter::make('type') + ->label(__('beneficiary.section.documents.labels.type')) + ->options(DocumentType::options()) + ->searchable(), + ]; + } + + public static function getFormComponents(): array + { + return [ + Select::make('type') + ->label(__('beneficiary.section.documents.labels.type')) + ->options(DocumentType::options()) + ->enum(DocumentType::class) + ->columnSpanFull() + ->required(), + + TextInput::make('name') + ->label(__('beneficiary.section.documents.labels.name')) + ->placeholder(__('beneficiary.placeholder.file_name')) + ->columnSpanFull() + ->maxLength(200) + ->required(), + + Textarea::make('observations') + ->placeholder(__('beneficiary.placeholder.observations')) + ->label(__('beneficiary.section.documents.labels.observations')) + ->columnSpanFull() + ->maxLength(500), + + SpatieMediaLibraryFileUpload::make('document_file') + ->label(__('beneficiary.section.documents.labels.document_file')) + ->openable() + ->downloadable() + ->acceptedFileTypes([ + 'application/pdf', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'text/csv', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'image/*', + ]) + ->maxSize(config('media-library.max_file_size')) + ->helperText(__('beneficiary.helper_text.document_file', [ + 'size' => Number::fileSize(config('media-library.max_file_size')), + ])) + ->columnSpanFull() + ->required(), + ]; + } +} diff --git a/app/Filament/Organizations/Schemas/ServiceResourceSchema.php b/app/Filament/Organizations/Schemas/ServiceResourceSchema.php new file mode 100644 index 00000000..600813ec --- /dev/null +++ b/app/Filament/Organizations/Schemas/ServiceResourceSchema.php @@ -0,0 +1,252 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing( + fn (Builder $query) => $query + ->with(['serviceWithoutStatusCondition', 'interventionServices.beneficiary']) + ->withCount(['interventions']) + ) + ->columns(self::getTableColumns()) + ->filters([]) + ->recordActions(self::getTableActions()) + ->heading(__('service.headings.list_table')) + ->headerActions(self::getTableHeaderActions()) + ->emptyStateIcon('heroicon-o-clipboard-document-check') + ->emptyStateHeading(__('service.headings.empty_state_table')) + ->emptyStateDescription(''); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->maxWidth('3xl') + ->schema([ + Placeholder::make('before_form') + ->hiddenLabel() + ->content(__('service.helper_texts.before_form')), + + Select::make('service_id') + ->label(__('service.labels.name')) + ->visible(fn (string $operation) => $operation === 'create') + ->relationship( + 'service', + 'name', + fn (Builder $query, $state) => $query->whereNotIn( + 'id', + OrganizationService::query() + ->whereNot('service_id', $state) + ->pluck('service_id') + ) + ) + ->afterStateUpdated(self::populateTable()) + ->live() + ->required(), + + Placeholder::make('service') + ->label(__('service.labels.name')) + ->content(fn ($record) => $record->serviceWithoutStatusCondition->name) + ->visible(fn (string $operation) => $operation === 'edit'), + + Notice::make('counseling_sheet_placeholder') + ->content(function (Get $get) { + $service = Service::find($get('service_id')); + + return $service?->counseling_sheet ? __('service.helper_texts.counseling_sheet') : null; + }) + ->icon('heroicon-o-document-text') + ->key('counseling_sheet_placeholder') + ->visible(fn (Get $get) => Service::find($get('service_id')) + ?->counseling_sheet) + ->registerActions([ + \Filament\Actions\Action::make('view_counseling_sheet') + ->label(__('service.actions.view_counseling_sheet')) + ->modalHeading( + fn (Get $get) => Service::find($get('service_id')) + ?->counseling_sheet + ?->getLabel() + ) + ->schema(function (Get $get) { + $service = Service::find($get('service_id')); + + $counselingSheet = $service?->counseling_sheet; + + if (! $counselingSheet) { + return null; + } + + if (CounselingSheet::isValue($counselingSheet, CounselingSheet::LEGAL_ASSISTANCE)) { + return EditCounselingSheet::getLegalAssistanceForm(); + } + + if (CounselingSheet::isValue($counselingSheet, CounselingSheet::PSYCHOLOGICAL_ASSISTANCE)) { + return EditCounselingSheet::getSchemaForPsychologicalAssistance(); + } + + return []; + }) + ->disabledForm() + ->modalAutofocus(false) + ->modalSubmitAction(fn (\Filament\Actions\Action $action) => $action->hidden()) + ->link(), + ]), + + Group::make() + ->visible(fn (Get $get) => $get('service_id')) + ->schema([ + Placeholder::make('counseling_sheet') + ->label(__('service.headings.interventions')) + ->content(__('service.helper_texts.interventions')), + + Repeater::make('interventions') + ->helperText(__('service.helper_texts.under_interventions_table')) + ->relationship('interventions') + ->addAction(fn (\Filament\Actions\Action $action) => $action->hidden()) + ->deletable(false) + ->reorderable(false) + ->mutateRelationshipDataBeforeCreateUsing(function (array $data) { + unset($data['active']); + + return $data; + }) + ->schema([ + Checkbox::make('active') + ->label(__('service.labels.select')) + ->afterStateUpdated(fn (bool $state, Set $set) => $state ? $set('status', true) : $set('status', false)) + ->live(), + + Placeholder::make('name') + ->label(__('service.labels.interventions')) + ->hiddenLabel() + ->content(fn ($state) => $state), + + Toggle::make('status') + ->label(__('service.labels.status')) + ->disabled(fn (Get $get) => ! $get('active')), + + Hidden::make('id'), + + Hidden::make('service_intervention_id'), + ]) + ->columns(3) + ->itemLabel(fn (array $state): ?string => $state['name'] ?? null) + ->collapsible() + ->afterStateHydrated(self::populateTable()), + ]), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('serviceWithoutStatusCondition.name') + ->label(__('service.labels.name')), + + TextColumn::make('interventions_count') + ->label(__('service.labels.interventions')), + + TextColumn::make('beneficiary') + ->label(__('service.labels.cases')) + ->default( + fn (OrganizationService $record) => $record->interventionServices + ->map(fn (InterventionService $item) => $item->beneficiary) + ->unique() + ->count() + ), + + TextColumn::make('status') + ->label(__('service.labels.status')), + ]; + } + + public static function getTableActions(): array + { + return [ + ViewAction::make() + ->label(__('general.action.view_details')), + ]; + } + + public static function getTableHeaderActions(): array + { + return [ + CreateAction::make() + ->label(__('service.actions.create')), + ]; + } + + public static function populateTable(): Closure + { + return function (Set $set, Get $get) { + $serviceID = $get('service_id'); + $interventions = ServiceIntervention::query() + ->where('service_id', $serviceID) + ->with('organizationIntervention') + ->active() + ->get(); + + $interventions->map(function (ServiceIntervention $intervention) { + $intervention->service_intervention_id = $intervention->id; + $intervention->id = $intervention->organizationIntervention?->id; + $intervention->status = $intervention->organizationIntervention?->status ?? false; + $intervention->active = isset($intervention->organizationIntervention) ?: false; + }); + + $set('interventions', $interventions->toArray()); + }; + } + + public static function processInterventionsBeforeSave(?array $interventions): ?array + { + foreach ($interventions as $key => &$intervention) { + if (! $intervention['active']) { + unset($interventions[$key]); + continue; + } + + unset($intervention['active']); + $intervention['status'] = (bool) $intervention['status']; + } + + return $interventions; + } +} diff --git a/app/Filament/Organizations/Schemas/UserResourceSchema.php b/app/Filament/Organizations/Schemas/UserResourceSchema.php new file mode 100644 index 00000000..cb1829a6 --- /dev/null +++ b/app/Filament/Organizations/Schemas/UserResourceSchema.php @@ -0,0 +1,253 @@ +components(self::getFormComponents()); + } + + public static function table(Table $table): Table + { + return $table + ->modifyQueryUsing(fn (Builder $query) => $query->with(['rolesInOrganization', 'userStatus'])) + ->heading(__('user.heading.table')) + ->columns(self::getTableColumns()) + ->recordActions(self::getTableActions()); + } + + public static function getFormComponents(): array + { + return [ + Section::make() + ->columns() + ->maxWidth('3xl') + ->visible(fn (string $operation) => $operation === 'edit') + ->schema([ + Placeholder::make('userStatus.status') + ->content(fn (User $record, $state) => $record->userStatus->status->getLabel()), + + Placeholder::make('last_login_at') + ->label(__('user.labels.last_login_at_date_time')) + ->content( + fn (User $record) => $record->last_login_at && $record->last_login_at !== '-' ? + $record->last_login_at->format('d.m.Y H:i:s') : + '-' + ), + ]), + + Section::make() + ->columns() + ->maxWidth('3xl') + ->schema([ + TextInput::make('first_name') + ->label(__('user.labels.first_name')) + ->required(), + + TextInput::make('last_name') + ->label(__('user.labels.last_name')) + ->required(), + + TextInput::make('email') + ->label(__('user.labels.email')) + ->email() + ->unique( + ignoreRecord: true, + modifyRuleUsing: fn (Unique $rule, string $operation) => $operation === 'edit' ? $rule : + $rule->whereIn('id', User::getTenantOrganizationUsers()->keys()) + ) + ->required(), + + TextInput::make('phone_number') + ->label(__('user.labels.phone_number')) + ->tel() + ->maxLength(14) + ->required(), + + Select::make('role_id') + ->label(__('user.labels.select_roles')) + ->relationship('rolesInOrganization', 'name') + ->options(Role::active()->pluck('name', 'id')) + ->preload() + ->multiple() + ->live() + ->required() + ->afterStateHydrated(self::setDefaultCaseAndNgoAdminPermissions()) + ->afterStateUpdated(self::setDefaultCaseAndNgoAdminPermissions()), + + Placeholder::make('obs') + ->hiddenLabel() + ->visible(fn (Get $get) => $get('role_id')) + ->content(function (Get $get) { + foreach ($get('role_id') as $roleID) { + $role = self::getRole($roleID); + if ($role->case_permissions->contains(CasePermission::HAS_ACCESS_TO_ALL_CASES)) { + return new HtmlString(__('user.placeholders.user_role_with_permissions_for_all_cases')); + } + } + + return new HtmlString(__('user.placeholders.user_role_without_permissions_for_all_cases')); + }) + ->columnSpanFull(), + + Group::make() + ->relationship('permissions') + ->columnSpanFull() + ->schema([ + CheckboxList::make('case_permissions') + ->label(__('user.labels.case_permissions')) + ->options(CasePermission::getOptionsWithoutCaseManager()) + ->disableOptionWhen(function (Get $get, string $value, ?OrganizationUserPermissions $record) { + if ($record?->user->isNgoAdmin()) { + return true; + } + + foreach ($get('../role_id') as $roleID) { + $role = self::getRole($roleID); + + $permission = $role->case_permissions + ->filter(fn ($item) => CasePermission::isValue($value, $item)); + if ($permission->count()) { + return true; + } + } + + return false; + }) + ->columnSpanFull(), + + CheckboxList::make('admin_permissions') + ->label(__('user.labels.admin_permissions')) + ->options(AdminPermission::options()) + ->disableOptionWhen(function (Get $get, string $value, ?OrganizationUserPermissions $record) { + if ($record?->user->isNgoAdmin()) { + return true; + } + + foreach ($get('../role_id') as $roleID) { + $role = self::getRole($roleID); + + $permission = $role->ngo_admin_permissions + ->filter(fn ($item) => AdminPermission::isValue($value, $item)); + if ($permission->count()) { + return true; + } + } + + return false; + }) + ->columnSpanFull(), + + Hidden::make('organization_id') + ->default(Filament::getTenant()->id), + ]), + ]), + ]; + } + + public static function getTableColumns(): array + { + return [ + TextColumn::make('first_name') + ->sortable() + ->label(__('user.labels.first_name')) + ->searchable(), + + TextColumn::make('last_name') + ->label(__('user.labels.last_name')) + ->searchable(), + + TextColumn::make('rolesInOrganization.name') + ->sortable() + ->label(__('user.labels.roles')), + + TextColumn::make('userStatus.status') + ->sortable() + ->label(__('user.labels.account_status')) + ->suffix(fn (User $record) => $record->isNgoAdmin() ? '**' : ''), + + \App\Tables\Columns\DateTimeColumn::make('last_login_at') + ->sortable() + ->label(__('user.labels.last_login_at')), + ]; + } + + public static function getTableActions(): array + { + return [ + \Filament\Actions\ViewAction::make() + ->label(__('general.action.view_details')), + ]; + } + + public static function setDefaultCaseAndNgoAdminPermissions(): Closure + { + return function (Set $set, Get $get, $state, ?User $record) { + $casePermissions = $get('permissions.case_permissions') ?: []; + $adminPermissions = $get('permissions.admin_permissions') ?: []; + + if ($record?->isNgoAdmin()) { + $casePermissions = CasePermission::values(); + $adminPermissions = AdminPermission::values(); + + $set('permissions.case_permissions', $casePermissions); + $set('permissions.admin_permissions', $adminPermissions); + + return; + } + + foreach ($state as $roleID) { + $role = self::getRole($roleID); + $defaultCasePermissions = $role->case_permissions?->map(fn ($item) => $item->value)->toArray(); + $defaultNgoAdminPermissions = $role->ngo_admin_permissions?->map(fn ($item) => $item->value)->toArray(); + + $casePermissions = array_merge($casePermissions, $defaultCasePermissions); + $adminPermissions = array_merge($adminPermissions, $defaultNgoAdminPermissions); + } + $casePermissions = array_unique($casePermissions); + $adminPermissions = array_unique($adminPermissions); + sort($casePermissions); + sort($adminPermissions); + + $set('permissions.case_permissions', $casePermissions); + $set('permissions.admin_permissions', $adminPermissions); + }; + } + + protected static function getRole(mixed $roleID) + { + return Cache::driver('array') + ->rememberForever( + 'role_' . $roleID, + fn () => Role::find($roleID) + ); + } +} diff --git a/app/Filament/Organizations/Widgets/CaseStatsWidget.php b/app/Filament/Organizations/Widgets/CaseStatsWidget.php index 61599508..fce5fd5f 100644 --- a/app/Filament/Organizations/Widgets/CaseStatsWidget.php +++ b/app/Filament/Organizations/Widgets/CaseStatsWidget.php @@ -12,7 +12,7 @@ class CaseStatsWidget extends BaseWidget { protected static bool $isLazy = false; - protected static ?string $pollingInterval = null; + protected ?string $pollingInterval = null; protected function getStats(): array { diff --git a/app/Filament/Organizations/Widgets/ConfigProgress.php b/app/Filament/Organizations/Widgets/ConfigProgress.php index 4d69b5ad..fa74e831 100644 --- a/app/Filament/Organizations/Widgets/ConfigProgress.php +++ b/app/Filament/Organizations/Widgets/ConfigProgress.php @@ -18,7 +18,7 @@ class ConfigProgress extends InfolistWidget { - protected static string $view = 'filament.organizations.widgets.config-progress'; + protected string $view = 'filament.organizations.widgets.config-progress'; protected Model | null $record = null; @@ -70,7 +70,7 @@ public function getInfolistSchema(): array SectionHeader::make('header') ->state(fn () => $this->getWidgetTitle()) ->action( - Action::make('close_action') + \Filament\Actions\Action::make('close_action') ->icon('heroicon-o-x-mark') ->iconButton() ->url(Dashboard::getUrl(['close_config_progress' => true])) diff --git a/app/Filament/Organizations/Widgets/DashboardInterventionsWidget.php b/app/Filament/Organizations/Widgets/DashboardInterventionsWidget.php index d4912546..83b84acb 100644 --- a/app/Filament/Organizations/Widgets/DashboardInterventionsWidget.php +++ b/app/Filament/Organizations/Widgets/DashboardInterventionsWidget.php @@ -4,6 +4,7 @@ namespace App\Filament\Organizations\Widgets; +use Filament\Actions\ViewAction; use App\Enums\DashboardIntervalFilter; use App\Filament\Organizations\Resources\BeneficiaryResource; use App\Filament\Organizations\Resources\InterventionServiceResource; @@ -74,8 +75,8 @@ public function table(Table $table): Table ->label(__('intervention_plan.labels.specialist')) ->searchable(), ]) - ->actions([ - Tables\Actions\ViewAction::make() + ->recordActions([ + ViewAction::make() ->label(__('intervention_plan.actions.view_intervention')) ->url( fn (BeneficiaryIntervention $record) => InterventionServiceResource::getUrl('view_intervention', [ @@ -90,7 +91,7 @@ public function table(Table $table): Table 'record' => $record, ]) ) - ->actionsColumnLabel(__('intervention_plan.labels.actions')) + ->recordActionsColumnLabel(__('intervention_plan.labels.actions')) ->filters([ SelectFilter::make('selected_interval') ->label(__('intervention_plan.labels.selected_interval')) diff --git a/app/Filament/Pages/Auth/RequestPasswordReset.php b/app/Filament/Pages/Auth/RequestPasswordReset.php index b067c176..4720a396 100644 --- a/app/Filament/Pages/Auth/RequestPasswordReset.php +++ b/app/Filament/Pages/Auth/RequestPasswordReset.php @@ -13,7 +13,7 @@ use Illuminate\Contracts\Auth\CanResetPassword; use Illuminate\Support\Facades\Password; -class RequestPasswordReset extends BaseRequestPasswordReset +class RequestPasswordReset extends \Filament\Auth\Pages\PasswordReset\RequestPasswordReset { public function request(): void { diff --git a/app/Filters/DateFilter.php b/app/Filters/DateFilter.php index 3e88f88b..e45ba6f2 100644 --- a/app/Filters/DateFilter.php +++ b/app/Filters/DateFilter.php @@ -31,8 +31,8 @@ protected function setUp(): void { parent::setUp(); - $this->form(fn () => [ - Fieldset::make($this->getLabel()) + $this->schema(fn () => [ + \Filament\Schemas\Components\Fieldset::make($this->getLabel()) ->columns($this->getColumns()) ->schema([ DatePicker::make('date_from') diff --git a/app/Forms/Components/Location.php b/app/Forms/Components/Location.php index f807e10b..d0a11c6d 100644 --- a/app/Forms/Components/Location.php +++ b/app/Forms/Components/Location.php @@ -8,22 +8,21 @@ use App\Models\City; use App\Models\County; use Closure; -use Filament\Forms\Components\Component; use Filament\Forms\Components\Concerns\CanBeValidated; -use Filament\Forms\Components\Concerns\EntanglesStateWithSingularRelationship; -use Filament\Forms\Components\Contracts\CanEntangleWithSingularRelationships; use Filament\Forms\Components\Hidden; use Filament\Forms\Components\TextInput; -use Filament\Forms\Get; -use Filament\Forms\Set; -use Illuminate\Support\Facades\Cache; +use Filament\Schemas\Components\Component; +use Filament\Schemas\Components\Concerns\EntanglesStateWithSingularRelationship; +use Filament\Schemas\Components\Contracts\CanEntangleWithSingularRelationships; +use Filament\Schemas\Components\Utilities\Get; +use Filament\Schemas\Components\Utilities\Set; class Location extends Component implements CanEntangleWithSingularRelationships { use EntanglesStateWithSingularRelationship; use CanBeValidated; - protected string $view = 'filament-forms::components.grid'; + protected string $view = 'filament-schemas::components.grid'; protected string | Closure | null $countyField = null; @@ -205,7 +204,7 @@ public function getEnvironmentLabel(): string ->join('_')); } - public function getChildComponents(): array + public function getDefaultChildComponents(): array { $addressInput = TextInput::make($this->getAddressField()) ->label($this->getAddressLabel()) @@ -228,16 +227,10 @@ public function getChildComponents(): array Select::make($this->getCountyField()) ->label($this->getCountyLabel()) ->placeholder(__('placeholder.county')) - ->options(function () { - return Cache::driver('array') - ->rememberForever( - 'counties', - fn () => County::pluck('name', 'id') - ); - }) + ->options(County::pluck('name', 'id')) ->searchable() ->preload() -// ->getSearchResultsUsing(fn (string $search): array => County::search($search)->get()->pluck('name', 'id')->toArray()) + ->getSearchResultsUsing(fn (string $search): array => County::search($search)->get()->pluck('name', 'id')->toArray()) ->live() ->required($this->isRequired()) ->disabled($this->isDisabled()) @@ -256,9 +249,8 @@ public function getChildComponents(): array ->live() ->searchable() ->required($this->isRequired()) - ->disabled(fn (Get $get) => $this->isDisabled() || ! $get($this->getCountyField())) + ->disabled(fn (Get $get) => $this->isDisabled() || ! debug($get($this->getCountyField()))) ->getSearchResultsUsing(function (string $search, Get $get) { - return City::search($search) ->where('county_id', (int) $get($this->getCountyField())) ->get() diff --git a/app/Forms/Components/Notice.php b/app/Forms/Components/Notice.php index 7614e45f..454b92e1 100644 --- a/app/Forms/Components/Notice.php +++ b/app/Forms/Components/Notice.php @@ -12,13 +12,13 @@ use Filament\Support\Concerns\HasIcon; use Filament\Support\Concerns\HasIconColor; -class Notice extends Placeholder implements HasAffixActions +class Notice extends Placeholder implements \Filament\Schemas\Components\Contracts\HasAffixActions { use HasIcon; use HasColor; use HasIconColor; use HasAffixes; - use HasKey; + use \Filament\Schemas\Components\Concerns\HasKey; protected string $view = 'forms.components.notice'; } diff --git a/app/Forms/Components/RadioTable.php b/app/Forms/Components/RadioTable.php index 1f69be2b..5cb7e838 100644 --- a/app/Forms/Components/RadioTable.php +++ b/app/Forms/Components/RadioTable.php @@ -4,19 +4,24 @@ namespace App\Forms\Components; +use Filament\Forms\Components\Concerns\CanBeCloned; +use Filament\Schemas\Components\Concerns\CanBeCollapsed; +use Filament\Forms\Components\Concerns\CanGenerateUuids; +use Filament\Forms\Components\Concerns\CanLimitItemsLength; +use Filament\Forms\Components\Concerns\HasContainerGridLayout; use Filament\Forms\Components\Concerns; use Filament\Forms\Components\Contracts\HasExtraItemActions; use Filament\Forms\Components\Field; use Filament\Forms\Components\Placeholder; use Filament\Support\Concerns\HasReorderAnimationDuration; -class RadioTable extends Field implements HasExtraItemActions +class RadioTable extends Field implements \Filament\Schemas\Components\Contracts\HasExtraItemActions { - use Concerns\CanBeCloned; - use Concerns\CanBeCollapsed; - use Concerns\CanGenerateUuids; - use Concerns\CanLimitItemsLength; - use Concerns\HasContainerGridLayout; + use CanBeCloned; + use CanBeCollapsed; + use CanGenerateUuids; + use CanLimitItemsLength; + use HasContainerGridLayout; use Concerns\HasExtraItemActions; use HasReorderAnimationDuration; @@ -64,7 +69,7 @@ public function setFields(array $fields): self return $this; } - public function getChildComponents(): array + public function getDefaultChildComponents(): array { $components = []; // foreach ($this->radioOptions as $key => $radioOption) { diff --git a/app/Forms/Components/ReportTable.php b/app/Forms/Components/ReportTable.php index f126f3c5..6c9c1cc2 100644 --- a/app/Forms/Components/ReportTable.php +++ b/app/Forms/Components/ReportTable.php @@ -9,7 +9,7 @@ use Filament\Infolists\Components\Component; use Illuminate\Support\Collection; -class ReportTable extends Component +class ReportTable extends \Filament\Schemas\Components\Component { protected string $view = 'forms.components.report-table'; diff --git a/app/Forms/Components/Spacer.php b/app/Forms/Components/Spacer.php index a34edc6e..d7b24943 100644 --- a/app/Forms/Components/Spacer.php +++ b/app/Forms/Components/Spacer.php @@ -6,7 +6,7 @@ use Filament\Forms\Components\Component; -class Spacer extends Component +class Spacer extends \Filament\Schemas\Components\Component { protected string $view = 'forms.components.spacer'; diff --git a/app/Forms/Components/TableRepeater.php b/app/Forms/Components/TableRepeater.php deleted file mode 100644 index c7b01232..00000000 --- a/app/Forms/Components/TableRepeater.php +++ /dev/null @@ -1,13 +0,0 @@ - [ - Middleware\EncryptCookies::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, - \Illuminate\Session\Middleware\StartSession::class, - \Illuminate\View\Middleware\ShareErrorsFromSession::class, - Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class, + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, ], 'api' => [ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, - \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api', - \Illuminate\Routing\Middleware\SubstituteBindings::class, + ThrottleRequests::class . ':api', + SubstituteBindings::class, ], ]; @@ -55,16 +78,16 @@ class Kernel extends HttpKernel * @var array */ protected $middlewareAliases = [ - 'auth' => Middleware\Authenticate::class, - 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, - 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, - 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, - 'can' => \Illuminate\Auth\Middleware\Authorize::class, - 'guest' => Middleware\RedirectIfAuthenticated::class, - 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, - 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, - 'signed' => Middleware\ValidateSignature::class, - 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, - 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'auth' => Authenticate::class, + 'auth.basic' => AuthenticateWithBasicAuth::class, + 'auth.session' => AuthenticateSession::class, + 'cache.headers' => SetCacheHeaders::class, + 'can' => Authorize::class, + 'guest' => RedirectIfAuthenticated::class, + 'password.confirm' => RequirePassword::class, + 'precognitive' => HandlePrecognitiveRequests::class, + 'signed' => ValidateSignature::class, + 'throttle' => ThrottleRequests::class, + 'verified' => EnsureEmailIsVerified::class, ]; } diff --git a/app/Http/Middleware/EnsureUserIsActive.php b/app/Http/Middleware/EnsureUserIsActive.php index 20bd977a..7551ce22 100644 --- a/app/Http/Middleware/EnsureUserIsActive.php +++ b/app/Http/Middleware/EnsureUserIsActive.php @@ -22,14 +22,14 @@ class EnsureUserIsActive { public function handle(Request $request, Closure $next): Response { - if (Filament::getCurrentPanel()->getId()=== 'admin' && auth()->user()->isAdmin()) { + if (Filament::getCurrentOrDefaultPanel()->getId()=== 'admin' && auth()->user()->isAdmin()) { return $next($request); } if ($this->userAndInstitutionIsActive() ) { return $next($request); } - if (Filament::getCurrentPanel()->getId() === 'organization') { + if (Filament::getCurrentOrDefaultPanel()->getId() === 'organization') { $activeOrganization = UserStatus::query() ->withoutGlobalScopes([BelongsToCurrentTenant::class]) ->where('user_id', auth()->id()) @@ -64,7 +64,7 @@ public function handle(Request $request, Closure $next): Response ]) : null) ->danger()->send(); - return redirect()->to(Filament::getCurrentPanel()->getLoginUrl()); + return redirect()->to(Filament::getCurrentOrDefaultPanel()->getLoginUrl()); } public function userAndInstitutionIsActive(): bool|RedirectResponse @@ -77,7 +77,7 @@ public function userAndInstitutionIsActive(): bool|RedirectResponse /** @var User $user */ $user = auth()->user(); - if ($user->isAdmin() && Filament::getCurrentPanel()->getId() === 'admin') { + if ($user->isAdmin() && Filament::getCurrentOrDefaultPanel()->getId() === 'admin') { $query->whereNull('organization_id'); } else { $query->where('organization_id', $user->latest_organization_id) diff --git a/app/Http/Middleware/UpdateDefaultTenant.php b/app/Http/Middleware/UpdateDefaultTenant.php index 1090498f..d5e53402 100644 --- a/app/Http/Middleware/UpdateDefaultTenant.php +++ b/app/Http/Middleware/UpdateDefaultTenant.php @@ -23,28 +23,28 @@ public function handle(Request $request, Closure $next): Response $user = Filament::auth()->user(); $tenant = Filament::getTenant(); - if ($user->latest_organization_id !== $tenant->id) { - $user->update([ - 'latest_organization_id' => $tenant->id, - ]); - - if ($tenant->institution->isInactivated()) { - return redirect()->to(Dashboard::getUrl()); - } - - if (! $user->userStatus) { - $user->initializeStatus(); - $user->loadMissing('userStatus'); - } - - if ($user->userStatus->status === UserStatus::PENDING) { - $user->userStatus->activate(); - } - - if ($tenant->institution->isPending()) { - $tenant->institution->activate(); - } - } +// if ($user->latest_organization_id !== $tenant->id) { +// $user->update([ +// 'latest_organization_id' => $tenant->id, +// ]); +// +// if ($tenant->institution->isInactivated()) { +// return redirect()->to(Dashboard::getUrl()); +// } +// +// if (! $user->userStatus) { +// $user->initializeStatus(); +// $user->loadMissing('userStatus'); +// } +// +// if ($user->userStatus->status === UserStatus::PENDING) { +// $user->userStatus->activate(); +// } +// +// if ($tenant->institution->isPending()) { +// $tenant->institution->activate(); +// } +// } return $next($request); } diff --git a/app/Http/Responses/LoginResponse.php b/app/Http/Responses/LoginResponse.php index ba8f4892..88da8e1e 100644 --- a/app/Http/Responses/LoginResponse.php +++ b/app/Http/Responses/LoginResponse.php @@ -9,7 +9,7 @@ use Illuminate\Http\RedirectResponse; use Livewire\Features\SupportRedirects\Redirector; -class LoginResponse implements Responsable +class LoginResponse implements \Filament\Auth\Http\Responses\Contracts\LoginResponse { public function toResponse($request): RedirectResponse | Redirector { diff --git a/app/Infolists/Components/Actions/CreateAction.php b/app/Infolists/Components/Actions/CreateAction.php index fa57be1a..93337ce1 100644 --- a/app/Infolists/Components/Actions/CreateAction.php +++ b/app/Infolists/Components/Actions/CreateAction.php @@ -4,6 +4,7 @@ namespace App\Infolists\Components\Actions; +use Filament\Schemas\Schema; use Closure; use Filament\Actions\Concerns\CanCustomizeProcess; use Filament\Actions\Concerns\InteractsWithRecord; @@ -14,7 +15,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; -class CreateAction extends Action +class CreateAction extends \Filament\Actions\Action { use CanCustomizeProcess; use InteractsWithRecord; @@ -24,7 +25,7 @@ class CreateAction extends Action protected function setUp(): void { parent::setUp(); - $this->action(function (array $arguments, Form $form): void { + $this->action(function (array $arguments, Schema $schema): void { $model = $this->getModel(); $record = $this->process(function (array $data, HasActions $livewire) use ($model): Model { @@ -48,7 +49,7 @@ protected function setUp(): void }); $this->record($record); - $form->model($record)->saveRelationships(); + $schema->model($record)->saveRelationships(); if ($arguments['another'] ?? false) { $this->callAfter(); @@ -57,9 +58,9 @@ protected function setUp(): void $this->record(null); // Ensure that the form record is anonymized so that relationships aren't loaded. - $form->model($model); + $schema->model($model); - $form->fill(); + $schema->fill(); $this->halt(); diff --git a/app/Infolists/Components/Actions/EditAction.php b/app/Infolists/Components/Actions/EditAction.php index 0f7355c3..f445a16c 100644 --- a/app/Infolists/Components/Actions/EditAction.php +++ b/app/Infolists/Components/Actions/EditAction.php @@ -7,7 +7,7 @@ use App\Concerns\HasModalExtraFooterActionsAlignment; use Filament\Infolists\Components\Actions\Action; -class EditAction extends Action +class EditAction extends \Filament\Actions\Action { use HasModalExtraFooterActionsAlignment; diff --git a/app/Infolists/Components/DocumentPreview.php b/app/Infolists/Components/DocumentPreview.php index eb1ec1d7..00ffef85 100644 --- a/app/Infolists/Components/DocumentPreview.php +++ b/app/Infolists/Components/DocumentPreview.php @@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Model; use Spatie\MediaLibrary\MediaCollections\Models\Media; -class DocumentPreview extends Component +class DocumentPreview extends \Filament\Schemas\Components\Component { protected string $view = 'infolists.components.document-preview'; @@ -40,12 +40,16 @@ public function getCollection(): string public function getFile(): ?Media { return $this->getRecord() - ->getFirstMedia($this->getCollection()); + ?->getFirstMedia($this->getCollection()); } - public function getRecord(): ?Model + public function getRecord(bool $withContainerRecord = true): Model|array|null { - return $this->evaluate($this->record) ?: parent::getRecord(); + $record = $this->evaluate($this->record); + if ($record !== null) { + return $record; + } + return parent::getRecord($withContainerRecord); } public function record(Model | Closure $record): static diff --git a/app/Infolists/Components/EnumEntry.php b/app/Infolists/Components/EnumEntry.php index 99ae1cfe..f49abd7c 100644 --- a/app/Infolists/Components/EnumEntry.php +++ b/app/Infolists/Components/EnumEntry.php @@ -4,6 +4,7 @@ namespace App\Infolists\Components; +use ReflectionEnum; use BackedEnum; use Filament\Infolists\Components\TextEntry; @@ -31,7 +32,7 @@ protected function setUp(): void if ($this->enumClass) { $state = collect(explode(',', $state)); - $reflectionClass = new \ReflectionEnum($this->enumClass); + $reflectionClass = new ReflectionEnum($this->enumClass); $returnType = $reflectionClass->getBackingtype(); return $state->map( diff --git a/app/Infolists/Components/HistoryLine.php b/app/Infolists/Components/HistoryLine.php index da222c6f..481d8e56 100644 --- a/app/Infolists/Components/HistoryLine.php +++ b/app/Infolists/Components/HistoryLine.php @@ -4,13 +4,14 @@ namespace App\Infolists\Components; +use Filament\Support\Enums\TextSize; use BackedEnum; use Filament\Infolists\Components\Component; use Filament\Infolists\Components\TextEntry; -class HistoryLine extends Component +class HistoryLine extends \Filament\Schemas\Components\Component { - protected string $view = 'filament-forms::components.grid'; + protected string $view = 'filament-schemas::components.grid'; protected string | null $fieldLabel = null; @@ -178,7 +179,7 @@ protected function getNewDescriptionId(): string return \sprintf('%s_new_description', $this->id); } - public function getChildComponents(): array + public function getDefaultChildComponents(): array { $hiddenDescriptions = blank($this->getOldDescription()) && blank($this->getNewDescription()); @@ -187,7 +188,7 @@ public function getChildComponents(): array ->hiddenLabel() ->state($this->getFieldHeading()) ->columnSpanFull() - ->size(TextEntry\TextEntrySize::Medium), + ->size(TextSize::Medium), TextEntry::make($this->getOldValueId()) ->hiddenLabel() diff --git a/app/Infolists/Components/Location.php b/app/Infolists/Components/Location.php index 8546e80a..40834016 100644 --- a/app/Infolists/Components/Location.php +++ b/app/Infolists/Components/Location.php @@ -11,11 +11,11 @@ use Filament\Infolists\Components\Concerns\EntanglesStateWithSingularRelationship; use Filament\Infolists\Components\TextEntry; -class Location extends Component +class Location extends \Filament\Schemas\Components\Component { - use EntanglesStateWithSingularRelationship; + use \Filament\Schemas\Components\Concerns\EntanglesStateWithSingularRelationship; - protected string $view = 'filament-forms::components.grid'; + protected string $view = 'filament-schemas::components.grid'; protected string | Closure | null $countyField = null; @@ -39,6 +39,8 @@ class Location extends Component protected string | Closure | null $environmentLabel = null; + protected string | Closure | null $label = null; + final public function __construct(string | null $id) { $this->id($id); @@ -61,6 +63,13 @@ protected function setUp(): void $this->columns(); } + public function label(string | Closure | null $label): static + { + $this->label = $label; + + return $this; + } + public function getCountyField(): string { return $this->getStatePath() ? 'county_id' : collect([ @@ -198,7 +207,7 @@ public function getEnvironmentLabel(): string ->join('_')); } - public function getChildComponents(): array + public function getDefaultChildComponents(): array { return [ TextEntry::make($this->getCountyField()) diff --git a/app/Infolists/Components/Notice.php b/app/Infolists/Components/Notice.php index 0a0292d8..e70658d3 100644 --- a/app/Infolists/Components/Notice.php +++ b/app/Infolists/Components/Notice.php @@ -4,16 +4,21 @@ namespace App\Infolists\Components; +use Filament\Infolists\Components\Concerns\HasColor; +use Filament\Support\Concerns\HasFontFamily; +use Filament\Infolists\Components\Concerns\HasIcon; +use Filament\Infolists\Components\Concerns\HasIconColor; +use Filament\Support\Concerns\HasWeight; use Filament\Infolists\Components\Concerns; use Filament\Infolists\Components\Entry; class Notice extends Entry { - use Concerns\HasColor; - use Concerns\HasFontFamily; - use Concerns\HasIcon; - use Concerns\HasIconColor; - use Concerns\HasWeight; + use HasColor; + use HasFontFamily; + use HasIcon; + use HasIconColor; + use HasWeight; /** * @var view-string diff --git a/app/Infolists/Components/SectionHeader.php b/app/Infolists/Components/SectionHeader.php index 484bd2c4..3f882a41 100644 --- a/app/Infolists/Components/SectionHeader.php +++ b/app/Infolists/Components/SectionHeader.php @@ -4,13 +4,16 @@ namespace App\Infolists\Components; +use Filament\Support\Concerns\HasFontFamily; +use Filament\Support\Concerns\HasWeight; +use Closure; use Filament\Infolists\Components\Concerns; use Filament\Infolists\Components\Entry; class SectionHeader extends Entry { - use Concerns\HasFontFamily; - use Concerns\HasWeight; + use HasFontFamily; + use HasWeight; protected $badge; @@ -19,7 +22,7 @@ class SectionHeader extends Entry */ protected string $view = 'components.section-header'; - public function badge(\Closure $param) + public function badge(Closure $param) { $this->badge = $param; diff --git a/app/Infolists/Components/TableEntry.php b/app/Infolists/Components/TableEntry.php index c69e8486..4f48d3a6 100644 --- a/app/Infolists/Components/TableEntry.php +++ b/app/Infolists/Components/TableEntry.php @@ -90,7 +90,7 @@ public function getHeaders(): array $customHeaders = $this->evaluate($this->headers); - foreach ($this->getChildComponents() as $field) { + foreach ($this->getDefaultChildComponents() as $field) { if ($field instanceof Hidden || $field->isHidden()) { continue; } diff --git a/app/Livewire/Welcome.php b/app/Livewire/Welcome.php index 7857daf9..3bf32f07 100644 --- a/app/Livewire/Welcome.php +++ b/app/Livewire/Welcome.php @@ -4,6 +4,7 @@ namespace App\Livewire; +use Filament\Schemas\Schema; use App\Models\User; use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException; use DanHarrin\LivewireRateLimiting\WithRateLimiting; @@ -27,7 +28,7 @@ class Welcome extends SimplePage /** * @var view-string */ - protected static string $view = 'livewire.welcome'; + protected string $view = 'livewire.welcome'; public User $user; @@ -61,7 +62,7 @@ public function getTitle(): string|Htmlable return __('auth.set_password'); } - public function handle(): ?LoginResponse + public function handle(): ?\Filament\Auth\Http\Responses\Contracts\LoginResponse { try { $this->rateLimit(5); @@ -84,13 +85,13 @@ public function handle(): ?LoginResponse Filament::auth()->login($this->user); - return app(LoginResponse::class); + return app(\Filament\Auth\Http\Responses\Contracts\LoginResponse::class); } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema([ + return $schema + ->components([ TextInput::make('email') ->label(__('filament-panels::pages/auth/register.form.email.label')) ->email() diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 00c959d9..16778fd3 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -49,12 +49,5 @@ public function scopeBetweenDates(Builder $query, ?string $from = null, ?string }); } - public function organization() - { - if (method_exists($this->subject, 'organization')) { - return $this->subject->organization(); - } - return null; - } } diff --git a/app/Models/City.php b/app/Models/City.php index 76c50145..58c0737e 100644 --- a/app/Models/City.php +++ b/app/Models/City.php @@ -4,6 +4,7 @@ namespace App\Models; +use Str; use App\Models\Scopes\AlphabeticalOrder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -90,23 +91,23 @@ public function getAliases(): array { $aliases = []; - if (\Str::of($this->name)->contains('Târgul')) { - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tg')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Târgu')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tirgul')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tirgu')->toString(); + if (Str::of($this->name)->contains('Târgul')) { + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tg')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Târgu')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tirgul')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tirgu')->toString(); } - if (\Str::of($this->name)->contains('Târgu')) { - $aliases[] = \Str::of($this->name)->replace('Târgu', 'Tg')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgu', 'Târgul')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgu', 'Tirgu')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgu', 'Tirgul')->toString(); + if (Str::of($this->name)->contains('Târgu')) { + $aliases[] = Str::of($this->name)->replace('Târgu', 'Tg')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgu', 'Târgul')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgu', 'Tirgu')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgu', 'Tirgul')->toString(); } - if (\Str::of($this->name)->contains('Satu')) { - $aliases[] = \Str::of($this->name)->replace('Satu', 'Sat')->toString(); - $aliases[] = \Str::of($this->name)->replace('Satu', 'Satu Mare')->toString(); + if (Str::of($this->name)->contains('Satu')) { + $aliases[] = Str::of($this->name)->replace('Satu', 'Sat')->toString(); + $aliases[] = Str::of($this->name)->replace('Satu', 'Satu Mare')->toString(); } return $aliases; diff --git a/app/Models/County.php b/app/Models/County.php index 8c506193..fa577252 100644 --- a/app/Models/County.php +++ b/app/Models/County.php @@ -4,6 +4,7 @@ namespace App\Models; +use Str; use App\Models\Scopes\AlphabeticalOrder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -46,16 +47,16 @@ public function getAliases(): array { $aliases = []; - if (\Str::of($this->name)->contains('Târgul')) { - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tg')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Târgu')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tirgul')->toString(); - $aliases[] = \Str::of($this->name)->replace('Târgul', 'Tirgu')->toString(); + if (Str::of($this->name)->contains('Târgul')) { + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tg')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Târgu')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tirgul')->toString(); + $aliases[] = Str::of($this->name)->replace('Târgul', 'Tirgu')->toString(); } - if (\Str::of($this->name)->contains('Satu')) { - $aliases[] = \Str::of($this->name)->replace('Satu', 'Sat')->toString(); - $aliases[] = \Str::of($this->name)->replace('Satu', 'Satu Mare')->toString(); + if (Str::of($this->name)->contains('Satu')) { + $aliases[] = Str::of($this->name)->replace('Satu', 'Sat')->toString(); + $aliases[] = Str::of($this->name)->replace('Satu', 'Satu Mare')->toString(); } return $aliases; diff --git a/app/Models/User.php b/app/Models/User.php index 86829302..ac25ef44 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -30,7 +30,6 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Collection; -use Jeffgreco13\FilamentBreezy\Traits\TwoFactorAuthenticatable; use Laravel\Sanctum\HasApiTokens; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\CausesActivity; @@ -48,7 +47,6 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasName, use LogsActivityOptions; use MustSetInitialPassword; use Notifiable; - use TwoFactorAuthenticatable; use HasPermissions; /** @@ -222,18 +220,18 @@ public function getDefaultTenant(Panel $panel): ?Model public function scopeWithLastLoginAt(Builder $query): Builder { - return $query - ->addSelect([ - 'last_login_at' => Activity::query() - ->select('created_at') - ->where('subject_type', $this->getMorphClass()) - ->whereColumn('subject_id', 'users.id') - ->where('log_name', 'system') - ->where('event', 'logged_in') - ->latest() - ->take(1), - ]) - ->withCasts(['last_login_at' => 'datetime']); + return $query; +// ->addSelect([ +// 'last_login_at' => Activity::query() +// ->select('created_at') +// ->where('subject_type', $this->getMorphClass()) +// ->whereColumn('subject_id', 'users.id') +// ->where('log_name', 'system') +// ->where('event', 'logged_in') +// ->latest() +// ->take(1), +// ]) +// ->withCasts(['last_login_at' => 'datetime']); } public function getFullNameAttribute(): string diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index c08d9eb1..174179f6 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -4,6 +4,60 @@ namespace App\Providers; +use App\Models\Activity; +use App\Models\Address; +use App\Models\Aggressor; +use App\Models\Beneficiary; +use App\Models\BeneficiaryAntecedents; +use App\Models\BeneficiaryDetails; +use App\Models\BeneficiaryIntervention; +use App\Models\BeneficiaryPartner; +use App\Models\BeneficiarySituation; +use App\Models\Benefit; +use App\Models\BenefitService; +use App\Models\BenefitType; +use App\Models\Children; +use App\Models\City; +use App\Models\CloseFile; +use App\Models\CommunityProfile; +use App\Models\Country; +use App\Models\County; +use App\Models\DetailedEvaluationResult; +use App\Models\DetailedEvaluationSpecialist; +use App\Models\Document; +use App\Models\EvaluateDetails; +use App\Models\FlowPresentation; +use App\Models\Institution; +use App\Models\InterventionMeeting; +use App\Models\InterventionPlan; +use App\Models\InterventionPlanResult; +use App\Models\InterventionService; +use App\Models\Meeting; +use App\Models\Monitoring; +use App\Models\MonitoringChild; +use App\Models\MonthlyPlan; +use App\Models\MonthlyPlanInterventions; +use App\Models\MonthlyPlanService; +use App\Models\MultidisciplinaryEvaluation; +use App\Models\Organization; +use App\Models\OrganizationService; +use App\Models\OrganizationServiceIntervention; +use App\Models\OrganizationUserPermissions; +use App\Models\ReferringInstitution; +use App\Models\RequestedServices; +use App\Models\Result; +use App\Models\RiskFactors; +use App\Models\Role; +use App\Models\Service; +use App\Models\ServiceCounselingSheet; +use App\Models\ServiceIntervention; +use App\Models\ServicePivot; +use App\Models\Specialist; +use App\Models\User; +use App\Models\UserRole; +use App\Models\UserStatus; +use App\Models\Violence; +use App\Models\ViolenceHistory; use App\Http\Responses\LoginResponse; use Filament\Forms\Components\TextInput; use Filament\Http\Responses\Auth\Contracts\LoginResponse as LoginResponseContract; @@ -29,7 +83,7 @@ public function register(): void $this->registerBlueprintMacros(); $this->registerViteMacros(); - $this->app->bind(LoginResponseContract::class, LoginResponse::class); + $this->app->bind(\Filament\Auth\Http\Responses\Contracts\LoginResponse::class, LoginResponse::class); Table::configureUsing(function (Table $table) { return $table->defaultSort('created_at', 'desc'); @@ -75,60 +129,60 @@ public function boot(): void protected function enforceMorphMap(): void { Relation::enforceMorphMap([ - 'activity' => \App\Models\Activity::class, - 'address' => \App\Models\Address::class, - 'aggressor' => \App\Models\Aggressor::class, - 'beneficiary' => \App\Models\Beneficiary::class, - 'beneficiaryAntecedents' => \App\Models\BeneficiaryAntecedents::class, - 'beneficiaryDetails' => \App\Models\BeneficiaryDetails::class, - 'beneficiaryIntervention' => \App\Models\BeneficiaryIntervention::class, - 'beneficiaryPartner' => \App\Models\BeneficiaryPartner::class, - 'beneficiarySituation' => \App\Models\BeneficiarySituation::class, - 'benefit' => \App\Models\Benefit::class, - 'benefitService' => \App\Models\BenefitService::class, - 'benefit_type' => \App\Models\BenefitType::class, - 'children' => \App\Models\Children::class, - 'city' => \App\Models\City::class, - 'closeFile' => \App\Models\CloseFile::class, - 'community_profile' => \App\Models\CommunityProfile::class, - 'country' => \App\Models\Country::class, - 'county' => \App\Models\County::class, - 'detailedEvaluationResult' => \App\Models\DetailedEvaluationResult::class, - 'detailedEvaluationSpecialist' => \App\Models\DetailedEvaluationSpecialist::class, - 'document' => \App\Models\Document::class, - 'evaluateDetails' => \App\Models\EvaluateDetails::class, - 'flowPresentation' => \App\Models\FlowPresentation::class, - 'institution' => \App\Models\Institution::class, - 'interventionMeeting' => \App\Models\InterventionMeeting::class, - 'interventionPlan' => \App\Models\InterventionPlan::class, - 'interventionPlanResult' => \App\Models\InterventionPlanResult::class, - 'interventionService' => \App\Models\InterventionService::class, - 'meeting' => \App\Models\Meeting::class, - 'monitoring' => \App\Models\Monitoring::class, - 'monitoringChild' => \App\Models\MonitoringChild::class, - 'monthlyPlan' => \App\Models\MonthlyPlan::class, - 'monthlyPlanInterventions' => \App\Models\MonthlyPlanInterventions::class, - 'monthlyPlanService' => \App\Models\MonthlyPlanService::class, - 'multidisciplinaryEvaluation' => \App\Models\MultidisciplinaryEvaluation::class, - 'organization' => \App\Models\Organization::class, - 'organization_service' => \App\Models\OrganizationService::class, - 'organization_service_intervention' => \App\Models\OrganizationServiceIntervention::class, - 'organization_user_permissions' => \App\Models\OrganizationUserPermissions::class, - 'referring_institution' => \App\Models\ReferringInstitution::class, - 'requestedServices' => \App\Models\RequestedServices::class, - 'result' => \App\Models\Result::class, - 'riskFactors' => \App\Models\RiskFactors::class, - 'role' => \App\Models\Role::class, - 'service' => \App\Models\Service::class, - 'service_counseling_sheet' => \App\Models\ServiceCounselingSheet::class, - 'service_intervention' => \App\Models\ServiceIntervention::class, - 'service_pivot' => \App\Models\ServicePivot::class, - 'specialist' => \App\Models\Specialist::class, - 'user' => \App\Models\User::class, - 'user_role' => \App\Models\UserRole::class, - 'user_status' => \App\Models\UserStatus::class, - 'violence' => \App\Models\Violence::class, - 'violenceHistory' => \App\Models\ViolenceHistory::class, + 'activity' => Activity::class, + 'address' => Address::class, + 'aggressor' => Aggressor::class, + 'beneficiary' => Beneficiary::class, + 'beneficiaryAntecedents' => BeneficiaryAntecedents::class, + 'beneficiaryDetails' => BeneficiaryDetails::class, + 'beneficiaryIntervention' => BeneficiaryIntervention::class, + 'beneficiaryPartner' => BeneficiaryPartner::class, + 'beneficiarySituation' => BeneficiarySituation::class, + 'benefit' => Benefit::class, + 'benefitService' => BenefitService::class, + 'benefit_type' => BenefitType::class, + 'children' => Children::class, + 'city' => City::class, + 'closeFile' => CloseFile::class, + 'community_profile' => CommunityProfile::class, + 'country' => Country::class, + 'county' => County::class, + 'detailedEvaluationResult' => DetailedEvaluationResult::class, + 'detailedEvaluationSpecialist' => DetailedEvaluationSpecialist::class, + 'document' => Document::class, + 'evaluateDetails' => EvaluateDetails::class, + 'flowPresentation' => FlowPresentation::class, + 'institution' => Institution::class, + 'interventionMeeting' => InterventionMeeting::class, + 'interventionPlan' => InterventionPlan::class, + 'interventionPlanResult' => InterventionPlanResult::class, + 'interventionService' => InterventionService::class, + 'meeting' => Meeting::class, + 'monitoring' => Monitoring::class, + 'monitoringChild' => MonitoringChild::class, + 'monthlyPlan' => MonthlyPlan::class, + 'monthlyPlanInterventions' => MonthlyPlanInterventions::class, + 'monthlyPlanService' => MonthlyPlanService::class, + 'multidisciplinaryEvaluation' => MultidisciplinaryEvaluation::class, + 'organization' => Organization::class, + 'organization_service' => OrganizationService::class, + 'organization_service_intervention' => OrganizationServiceIntervention::class, + 'organization_user_permissions' => OrganizationUserPermissions::class, + 'referring_institution' => ReferringInstitution::class, + 'requestedServices' => RequestedServices::class, + 'result' => Result::class, + 'riskFactors' => RiskFactors::class, + 'role' => Role::class, + 'service' => Service::class, + 'service_counseling_sheet' => ServiceCounselingSheet::class, + 'service_intervention' => ServiceIntervention::class, + 'service_pivot' => ServicePivot::class, + 'specialist' => Specialist::class, + 'user' => User::class, + 'user_role' => UserRole::class, + 'user_status' => UserStatus::class, + 'violence' => Violence::class, + 'violenceHistory' => ViolenceHistory::class, ]); } @@ -139,7 +193,7 @@ protected function registerBlueprintMacros(): void ->filter() ->join('_'); - return $this->foreignIdFor(\App\Models\County::class, $column) + return $this->foreignIdFor(County::class, $column) ->nullable() ->constrained('countries') ->cascadeOnDelete(); @@ -150,7 +204,7 @@ protected function registerBlueprintMacros(): void ->filter() ->join('_'); - return $this->foreignIdFor(\App\Models\City::class, $column) + return $this->foreignIdFor(City::class, $column) ->nullable() ->constrained('cities') ->cascadeOnDelete(); diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 4d5a44d1..543beed0 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -4,6 +4,10 @@ namespace App\Providers\Filament; +use App\Filament\Admin\Pages\Auth\Login; +use App\Filament\Admin\Pages\Dashboard; +use Filament\Actions\Action; +use Filament\Schemas\Schema; use App\Filament\Admin\Pages; use App\Filament\Admin\Resources\ServiceResource; use App\Filament\Pages\Auth\RequestPasswordReset; @@ -31,7 +35,6 @@ use Illuminate\Session\Middleware\StartSession; use Illuminate\Support\Facades\Route; use Illuminate\View\Middleware\ShareErrorsFromSession; -use Jeffgreco13\FilamentBreezy\BreezyCore; class AdminPanelProvider extends PanelProvider { @@ -59,7 +62,7 @@ public function panel(Panel $panel): Panel ->path('admin') ->sidebarCollapsibleOnDesktop() ->collapsibleNavigationGroups(false) - ->login(Pages\Auth\Login::class) + ->login(Login::class) ->passwordReset(RequestPasswordReset::class) ->colors([ 'primary' => Color::Amber, @@ -79,7 +82,7 @@ public function panel(Panel $panel): Panel for: 'App\\Filament\\Admin\\Pages' ) ->pages([ - Pages\Dashboard::class, + Dashboard::class, ]) ->routes(function () { Route::get('/welcome/{user:ulid}', Welcome::class)->name('auth.welcome'); @@ -94,7 +97,7 @@ public function panel(Panel $panel): Panel ->bootUsing(function () { Page::stickyFormActions(); Page::alignFormActionsEnd(); - MountableAction::configureUsing(function (MountableAction $action) { + Action::configureUsing(function (Action $action) { $action->modalFooterActionsAlignment(Alignment::Right); }); }) @@ -111,12 +114,12 @@ public function panel(Panel $panel): Panel ]) ->unsavedChangesAlerts() ->plugins([ - BreezyCore::make() - ->myProfile( - hasAvatars: true, - slug: 'settings' - ) - ->enableTwoFactorAuthentication(), +// BreezyCore::make() +// ->myProfile( +// hasAvatars: true, +// slug: 'settings' +// ) +// ->enableTwoFactorAuthentication(), ]) ->middleware([ EncryptCookies::class, @@ -137,18 +140,18 @@ public function panel(Panel $panel): Panel protected function setDefaultDateTimeDisplayFormats(): void { - Table::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - Table::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - Table::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; + Table::configureUsing(fn(Table $table) => $table->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + Table::configureUsing(fn(Table $table) => $table->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + Table::configureUsing(fn(Table $table) => $table->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); - Infolist::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - Infolist::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - Infolist::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; + Schema::configureUsing(fn(Schema $schema) => $schema->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + Schema::configureUsing(fn(Schema $schema) => $schema->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + Schema::configureUsing(fn(Schema $schema) => $schema->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); - DateTimePicker::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - DateTimePicker::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - DateTimePicker::$defaultDateTimeWithSecondsDisplayFormat = static::$defaultDateTimeWithSecondsDisplayFormat; - DateTimePicker::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; - DateTimePicker::$defaultTimeWithSecondsDisplayFormat = static::$defaultTimeWithSecondsDisplayFormat; + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateTimeWithSecondsDisplayFormat(static::$defaultDateTimeWithSecondsDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultTimeWithSecondsDisplayFormat(static::$defaultTimeWithSecondsDisplayFormat)); } } diff --git a/app/Providers/Filament/OrganizationPanelProvider.php b/app/Providers/Filament/OrganizationPanelProvider.php index b4be4954..fcb46dfc 100644 --- a/app/Providers/Filament/OrganizationPanelProvider.php +++ b/app/Providers/Filament/OrganizationPanelProvider.php @@ -4,8 +4,11 @@ namespace App\Providers\Filament; +use App\Filament\Organizations\Pages\Auth\Login; +use App\Filament\Organizations\Pages\Dashboard; +use Filament\Actions\Action; +use Filament\Schemas\Schema; use App\Filament\Organizations\Pages; -use App\Filament\Organizations\Pages\Profile\UserPersonalInfo; use App\Filament\Pages\Auth\RequestPasswordReset; use App\Http\Middleware\EnsureUserIsActive; use App\Http\Middleware\UpdateDefaultTenant; @@ -33,8 +36,6 @@ use Illuminate\Session\Middleware\StartSession; use Illuminate\Support\Facades\Route; use Illuminate\View\Middleware\ShareErrorsFromSession; -use Jeffgreco13\FilamentBreezy\BreezyCore; -use Livewire\Livewire; class OrganizationPanelProvider extends PanelProvider { @@ -57,7 +58,7 @@ public function register(): void public function boot(): void { - Livewire::component('user_personal_info', UserPersonalInfo::class); + // UserPersonalInfo is now a standalone Livewire component } public function panel(Panel $panel): Panel @@ -67,7 +68,7 @@ public function panel(Panel $panel): Panel ->id('organization') ->sidebarCollapsibleOnDesktop() ->collapsibleNavigationGroups(false) - ->login(Pages\Auth\Login::class) + ->login(Login::class) ->passwordReset(RequestPasswordReset::class) ->colors([ 'primary' => Color::Violet, @@ -87,7 +88,7 @@ public function panel(Panel $panel): Panel for: 'App\\Filament\\Organizations\\Pages' ) ->pages([ - Pages\Dashboard::class, + Dashboard::class, ]) ->routes(function () { Route::get('/welcome/{user:ulid}', Welcome::class)->name('auth.welcome'); @@ -102,25 +103,14 @@ public function panel(Panel $panel): Panel ->bootUsing(function () { Page::stickyFormActions(); Page::alignFormActionsEnd(); - MountableAction::configureUsing(function (MountableAction $action) { + Action::configureUsing(function (Action $action) { $action->modalFooterActionsAlignment(Alignment::Right); }); }) ->unsavedChangesAlerts() // ->databaseNotifications() ->plugins([ - BreezyCore::make() - ->myProfile( - hasAvatars: true, - slug: 'settings' - ) - ->myProfileComponents([ - 'personal_info' => UserPersonalInfo::class, - ]) - ->passwordUpdateRules([ - 'password' => 'required|confirmed|min:8', - ]) - ->enableTwoFactorAuthentication(), + // Breezy removed - using native Filament profile ]) ->navigationItems([ NavigationItem::make(__('navigation.configurations.organization')) @@ -156,18 +146,18 @@ public function panel(Panel $panel): Panel protected function setDefaultDateTimeDisplayFormats(): void { - Table::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - Table::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - Table::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; + Table::configureUsing(fn(Table $table) => $table->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + Table::configureUsing(fn(Table $table) => $table->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + Table::configureUsing(fn(Table $table) => $table->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); - Infolist::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - Infolist::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - Infolist::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; + Schema::configureUsing(fn(Schema $schema) => $schema->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + Schema::configureUsing(fn(Schema $schema) => $schema->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + Schema::configureUsing(fn(Schema $schema) => $schema->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); - DateTimePicker::$defaultDateDisplayFormat = static::$defaultDateDisplayFormat; - DateTimePicker::$defaultDateTimeDisplayFormat = static::$defaultDateTimeDisplayFormat; - DateTimePicker::$defaultDateTimeWithSecondsDisplayFormat = static::$defaultDateTimeWithSecondsDisplayFormat; - DateTimePicker::$defaultTimeDisplayFormat = static::$defaultTimeDisplayFormat; - DateTimePicker::$defaultTimeWithSecondsDisplayFormat = static::$defaultTimeWithSecondsDisplayFormat; + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateDisplayFormat(static::$defaultDateDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateTimeDisplayFormat(static::$defaultDateTimeDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultDateTimeWithSecondsDisplayFormat(static::$defaultDateTimeWithSecondsDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultTimeDisplayFormat(static::$defaultTimeDisplayFormat)); + DateTimePicker::configureUsing(fn(DateTimePicker $dateTimePicker) => $dateTimePicker->defaultTimeWithSecondsDisplayFormat(static::$defaultTimeWithSecondsDisplayFormat)); } } diff --git a/app/Rules/MultipleIn.php b/app/Rules/MultipleIn.php index bdd4dee6..7e73a2d1 100644 --- a/app/Rules/MultipleIn.php +++ b/app/Rules/MultipleIn.php @@ -4,6 +4,7 @@ namespace App\Rules; +use Illuminate\Translation\PotentiallyTranslatedString; use Closure; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Support\Arr; @@ -27,7 +28,7 @@ public function __construct(iterable $allowedValues) /** * Run the validation rule. * - * @param Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail + * @param Closure(string):PotentiallyTranslatedString $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { diff --git a/app/Rules/ValidCIF.php b/app/Rules/ValidCIF.php index 4a053c77..401baae3 100644 --- a/app/Rules/ValidCIF.php +++ b/app/Rules/ValidCIF.php @@ -4,6 +4,7 @@ namespace App\Rules; +use Illuminate\Translation\PotentiallyTranslatedString; use Closure; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Support\Str; @@ -13,7 +14,7 @@ class ValidCIF implements ValidationRule /** * Run the validation rule. * - * @param Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail + * @param Closure(string):PotentiallyTranslatedString $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { diff --git a/app/Rules/ValidCNP.php b/app/Rules/ValidCNP.php index 3e4075d4..9d413917 100644 --- a/app/Rules/ValidCNP.php +++ b/app/Rules/ValidCNP.php @@ -4,6 +4,7 @@ namespace App\Rules; +use Illuminate\Translation\PotentiallyTranslatedString; use alcea\cnp\Cnp; use Closure; use Illuminate\Contracts\Validation\ValidationRule; @@ -13,7 +14,7 @@ class ValidCNP implements ValidationRule /** * Run the validation rule. * - * @param Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail + * @param Closure(string):PotentiallyTranslatedString $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { diff --git a/app/Tables/Actions/EditAction.php b/app/Tables/Actions/EditAction.php index 05ec3d4a..8e4a6054 100644 --- a/app/Tables/Actions/EditAction.php +++ b/app/Tables/Actions/EditAction.php @@ -7,7 +7,7 @@ use App\Concerns\HasModalExtraFooterActionsAlignment; use Filament\Tables\Actions\EditAction as BaseEditAction; -class EditAction extends BaseEditAction +class EditAction extends \Filament\Actions\EditAction { use HasModalExtraFooterActionsAlignment; diff --git a/app/Tables/Columns/ServiceChipsColumn.php b/app/Tables/Columns/ServiceChipsColumn.php index 4a57e9fe..943a95f3 100644 --- a/app/Tables/Columns/ServiceChipsColumn.php +++ b/app/Tables/Columns/ServiceChipsColumn.php @@ -4,6 +4,7 @@ namespace App\Tables\Columns; +use Filament\Tables\Columns\Concerns\HasColor; use Closure; use Filament\Tables\Columns\Column; use Filament\Tables\Columns\Concerns; @@ -11,7 +12,7 @@ class ServiceChipsColumn extends Column { - use Concerns\HasColor; + use HasColor; protected string $view = 'tables.columns.service-chips-column'; diff --git a/app/Tables/Filters/ServicesFilter.php b/app/Tables/Filters/ServicesFilter.php index 1f0376e7..b6b7e0bb 100644 --- a/app/Tables/Filters/ServicesFilter.php +++ b/app/Tables/Filters/ServicesFilter.php @@ -4,6 +4,8 @@ namespace App\Tables\Filters; +use Filament\Tables\Filters\Concerns\HasOptions; +use Filament\Tables\Filters\Concerns\HasRelationship; use App\Models\Service; use Closure; use Filament\Forms\Components\CheckboxList; @@ -16,8 +18,8 @@ class ServicesFilter extends BaseFilter { - use Concerns\HasOptions; - use Concerns\HasRelationship; + use HasOptions; + use HasRelationship; protected string | Closure | null $attribute = null; diff --git a/app/Widgets/FormWidget.php b/app/Widgets/FormWidget.php index 453ba220..203a9ca9 100644 --- a/app/Widgets/FormWidget.php +++ b/app/Widgets/FormWidget.php @@ -11,5 +11,5 @@ class FormWidget extends InfolistWidget implements HasForms { use InteractsWithForms; - protected static string $view = 'widgets.form-widget'; + protected string $view = 'widgets.form-widget'; } diff --git a/app/Widgets/InfolistWidget.php b/app/Widgets/InfolistWidget.php index 05004014..5084b9f0 100644 --- a/app/Widgets/InfolistWidget.php +++ b/app/Widgets/InfolistWidget.php @@ -4,6 +4,7 @@ namespace App\Widgets; +use Filament\Schemas\Schema; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; use Filament\Forms\Concerns\InteractsWithForms; @@ -22,14 +23,14 @@ class InfolistWidget extends Widget implements HasInfolists, HasForms, HasAction use InteractsWithForms; use InteractsWithHeaderActions; - protected static string $view = 'widgets.infolist-widget'; + protected string $view = 'widgets.infolist-widget'; protected function getWidgetInfolist() { - return Infolist::make() + return Schema::make() ->record($this->record) ->name($this->getDisplayName()) - ->schema($this->getInfolistSchema()); + ->components($this->getInfolistSchema()); } protected function getInfolistSchema(): array diff --git a/boost.json b/boost.json new file mode 100644 index 00000000..70a1911a --- /dev/null +++ b/boost.json @@ -0,0 +1,22 @@ +{ + "agents": [ + "cursor", + "codex", + "claude_code", + "gemini", + "copilot", + "junie", + "opencode" + ], + "guidelines": true, + "herd_mcp": false, + "mcp": true, + "packages": [ + "filament/filament" + ], + "sail": false, + "skills": [ + "pest-testing", + "tailwindcss-development" + ] +} diff --git a/composer.json b/composer.json index b7523cbe..21c545ff 100644 --- a/composer.json +++ b/composer.json @@ -12,36 +12,33 @@ ], "license": "MPL-2.0", "require": { - "php": "^8.2", + "php": "^8.4", "alcea/cnp": "^3.0", - "awcodes/filament-table-repeater": "^3.1", "blade-ui-kit/blade-icons": "^1.6", - "filament/filament": "^3.2", - "filament/spatie-laravel-media-library-plugin": "^3.2", + "filament/filament": "^4.0", + "filament/spatie-laravel-media-library-plugin": "^4.0", "guzzlehttp/guzzle": "^7.2", - "jeffgreco13/filament-breezy": "^2.5", - "kenepa/multi-widget": "^2.0", - "laravel/framework": "^11.41", + "laravel/framework": "^12.41", "laravel/sanctum": "^4.0", + "laravel/scout": "^10.14", "laravel/tinker": "^2.10", "league/flysystem-aws-s3-v3": "^3.28", "maatwebsite/excel": "^3.1", - "pxlrbt/filament-excel": "^2.3", "sentry/sentry-laravel": "^4.11", "spatie/laravel-activitylog": "^4.9", "staudenmeir/belongs-to-through": "^2.5", "staudenmeir/eloquent-has-many-deep": "^1.7", "stevegrunwell/time-constants": "^1.2", "tpetry/laravel-query-expressions": "^1.4", - "laravel/scout": "^10.14", "typesense/typesense-php": "^5.0" - }, "require-dev": { "barryvdh/laravel-debugbar": "^3.14", "barryvdh/laravel-ide-helper": "^3.5", "fakerphp/faker": "^1.24", + "filament/upgrade": "^4.0", "friendsofphp/php-cs-fixer": "^3.68", + "laravel/boost": "*", "laravel/pint": "^1.20", "laravel/sail": "^1.41", "mockery/mockery": "^1.4.4", diff --git a/composer.lock b/composer.lock index 65635ff1..86ce5395 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1ba9551452e8dcd538491f74589e201d", + "content-hash": "3ad70b0a58f1ea710189fabf6e19d9e0", "packages": [ { "name": "alcea/cnp", @@ -64,16 +64,16 @@ }, { "name": "anourvalar/eloquent-serialize", - "version": "1.3.3", + "version": "1.3.5", "source": { "type": "git", "url": "https://github.com/AnourValar/eloquent-serialize.git", - "reference": "2f05023f1e465a91dc4f08483e6710325641a444" + "reference": "1a7dead8d532657e5358f8f27c0349373517681e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/2f05023f1e465a91dc4f08483e6710325641a444", - "reference": "2f05023f1e465a91dc4f08483e6710325641a444", + "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/1a7dead8d532657e5358f8f27c0349373517681e", + "reference": "1a7dead8d532657e5358f8f27c0349373517681e", "shasum": "" }, "require": { @@ -124,84 +124,9 @@ ], "support": { "issues": "https://github.com/AnourValar/eloquent-serialize/issues", - "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.3" + "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.5" }, - "time": "2025-05-28T17:07:28+00:00" - }, - { - "name": "awcodes/filament-table-repeater", - "version": "v3.1.4", - "source": { - "type": "git", - "url": "https://github.com/awcodes/filament-table-repeater.git", - "reference": "275de32e2123a2f7e586404352ee4c794f019a09" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-table-repeater/zipball/275de32e2123a2f7e586404352ee4c794f019a09", - "reference": "275de32e2123a2f7e586404352ee4c794f019a09", - "shasum": "" - }, - "require": { - "filament/forms": "^3.2.116", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.13.5" - }, - "require-dev": { - "laravel/pint": "^1.0", - "nunomaduro/collision": "^7.0", - "orchestra/testbench": "^8.0", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-faker": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", - "pestphp/pest-plugin-livewire": "^2.0", - "phpunit/phpunit": "^10.0", - "spatie/laravel-ray": "^1.26" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Awcodes\\TableRepeater\\TableRepeaterServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Awcodes\\TableRepeater\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Adam Weston", - "email": "awcodes1@gmail.com", - "role": "Developer" - } - ], - "description": "A modified version of the Filament Forms Repeater to display it as a table.", - "homepage": "https://github.com/awcodes/filament-table-repeater", - "keywords": [ - "awcodes", - "filament", - "laravel", - "plugin", - "table repeater" - ], - "support": { - "issues": "https://github.com/awcodes/filament-table-repeater/issues", - "source": "https://github.com/awcodes/filament-table-repeater/tree/v3.1.4" - }, - "funding": [ - { - "url": "https://github.com/awcodes", - "type": "github" - } - ], - "time": "2025-05-15T15:46:52+00:00" + "time": "2025-12-04T13:38:21+00:00" }, { "name": "aws/aws-crt-php", @@ -259,16 +184,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.351.4", + "version": "3.369.20", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "19dfd2db0f6ce35e1947e8bff4d956614b4aaaaf" + "reference": "f53d8fc6cdbc1e64e7d14e72d1e315d05003b2b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/19dfd2db0f6ce35e1947e8bff4d956614b4aaaaf", - "reference": "19dfd2db0f6ce35e1947e8bff4d956614b4aaaaf", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f53d8fc6cdbc1e64e7d14e72d1e315d05003b2b4", + "reference": "f53d8fc6cdbc1e64e7d14e72d1e315d05003b2b4", "shasum": "" }, "require": { @@ -281,7 +206,8 @@ "guzzlehttp/psr7": "^2.4.5", "mtdowling/jmespath.php": "^2.8.0", "php": ">=8.1", - "psr/http-message": "^2.0" + "psr/http-message": "^1.0 || ^2.0", + "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -292,13 +218,11 @@ "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", - "ext-pcntl": "*", "ext-sockets": "*", - "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "phpunit/phpunit": "^9.6", "psr/cache": "^2.0 || ^3.0", "psr/simple-cache": "^2.0 || ^3.0", "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", - "symfony/filesystem": "^v6.4.0 || ^v7.1.0", "yoast/phpunit-polyfills": "^2.0" }, "suggest": { @@ -306,6 +230,7 @@ "doctrine/cache": "To use the DoctrineCacheAdapter", "ext-curl": "To send requests using cURL", "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-pcntl": "To use client-side monitoring", "ext-sockets": "To use client-side monitoring" }, "type": "library", @@ -350,63 +275,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.351.4" - }, - "time": "2025-07-22T18:12:04+00:00" - }, - { - "name": "bacon/bacon-qr-code", - "version": "v3.0.1", - "source": { - "type": "git", - "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f", - "shasum": "" - }, - "require": { - "dasprid/enum": "^1.0.3", - "ext-iconv": "*", - "php": "^8.1" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.20" }, - "require-dev": { - "phly/keep-a-changelog": "^2.12", - "phpunit/phpunit": "^10.5.11 || 11.0.4", - "spatie/phpunit-snapshot-assertions": "^5.1.5", - "squizlabs/php_codesniffer": "^3.9" - }, - "suggest": { - "ext-imagick": "to generate QR code images" - }, - "type": "library", - "autoload": { - "psr-4": { - "BaconQrCode\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Ben Scholzen 'DASPRiD'", - "email": "mail@dasprids.de", - "homepage": "https://dasprids.de/", - "role": "Developer" - } - ], - "description": "BaconQrCode is a QR code generator for PHP.", - "homepage": "https://github.com/Bacon/BaconQrCode", - "support": { - "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1" - }, - "time": "2024-10-01T13:55:55+00:00" + "time": "2026-01-26T19:14:05+00:00" }, { "name": "blade-ui-kit/blade-heroicons", @@ -479,16 +350,16 @@ }, { "name": "blade-ui-kit/blade-icons", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/driesvints/blade-icons.git", - "reference": "7b743f27476acb2ed04cb518213d78abe096e814" + "reference": "47e7b6f43250e6404e4224db8229219cd42b543c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/7b743f27476acb2ed04cb518213d78abe096e814", - "reference": "7b743f27476acb2ed04cb518213d78abe096e814", + "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/47e7b6f43250e6404e4224db8229219cd42b543c", + "reference": "47e7b6f43250e6404e4224db8229219cd42b543c", "shasum": "" }, "require": { @@ -535,7 +406,7 @@ } ], "description": "A package to easily make use of icons in your Laravel Blade views.", - "homepage": "https://github.com/blade-ui-kit/blade-icons", + "homepage": "https://github.com/driesvints/blade-icons", "keywords": [ "blade", "icons", @@ -543,8 +414,8 @@ "svg" ], "support": { - "issues": "https://github.com/blade-ui-kit/blade-icons/issues", - "source": "https://github.com/blade-ui-kit/blade-icons" + "issues": "https://github.com/driesvints/blade-icons/issues", + "source": "https://github.com/driesvints/blade-icons" }, "funding": [ { @@ -556,29 +427,29 @@ "type": "paypal" } ], - "time": "2025-02-13T20:35:06+00:00" + "time": "2026-01-20T09:46:32+00:00" }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "6.8.8" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -608,7 +479,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -616,7 +487,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -687,6 +558,165 @@ ], "time": "2024-02-09T16:56:22+00:00" }, + { + "name": "chillerlan/php-qrcode", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/chillerlan/php-qrcode.git", + "reference": "7b66282572fc14075c0507d74d9837dab25b38d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/7b66282572fc14075c0507d74d9837dab25b38d6", + "reference": "7b66282572fc14075c0507d74d9837dab25b38d6", + "shasum": "" + }, + "require": { + "chillerlan/php-settings-container": "^2.1.6 || ^3.2.1", + "ext-mbstring": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "chillerlan/php-authenticator": "^4.3.1 || ^5.2.1", + "ext-fileinfo": "*", + "phan/phan": "^5.5.2", + "phpcompatibility/php-compatibility": "10.x-dev", + "phpmd/phpmd": "^2.15", + "phpunit/phpunit": "^9.6", + "setasign/fpdf": "^1.8.2", + "slevomat/coding-standard": "^8.23.0", + "squizlabs/php_codesniffer": "^4.0.0" + }, + "suggest": { + "chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.", + "setasign/fpdf": "Required to use the QR FPDF output.", + "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code" + }, + "type": "library", + "autoload": { + "psr-4": { + "chillerlan\\QRCode\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT", + "Apache-2.0" + ], + "authors": [ + { + "name": "Kazuhiko Arase", + "homepage": "https://github.com/kazuhikoarase/qrcode-generator" + }, + { + "name": "ZXing Authors", + "homepage": "https://github.com/zxing/zxing" + }, + { + "name": "Ashot Khanamiryan", + "homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder" + }, + { + "name": "Smiley", + "email": "smiley@chillerlan.net", + "homepage": "https://github.com/codemasher" + }, + { + "name": "Contributors", + "homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors" + } + ], + "description": "A QR Code generator and reader with a user-friendly API. PHP 7.4+", + "homepage": "https://github.com/chillerlan/php-qrcode", + "keywords": [ + "phpqrcode", + "qr", + "qr code", + "qr-reader", + "qrcode", + "qrcode-generator", + "qrcode-reader" + ], + "support": { + "docs": "https://php-qrcode.readthedocs.io", + "issues": "https://github.com/chillerlan/php-qrcode/issues", + "source": "https://github.com/chillerlan/php-qrcode" + }, + "funding": [ + { + "url": "https://ko-fi.com/codemasher", + "type": "Ko-Fi" + } + ], + "time": "2025-11-23T23:51:44+00:00" + }, + { + "name": "chillerlan/php-settings-container", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/chillerlan/php-settings-container.git", + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681", + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.1" + }, + "require-dev": { + "phpmd/phpmd": "^2.15", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-deprecation-rules": "^1.2", + "phpunit/phpunit": "^10.5", + "squizlabs/php_codesniffer": "^3.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "chillerlan\\Settings\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Smiley", + "email": "smiley@chillerlan.net", + "homepage": "https://github.com/codemasher" + } + ], + "description": "A container class for immutable settings objects. Not a DI container.", + "homepage": "https://github.com/chillerlan/php-settings-container", + "keywords": [ + "Settings", + "configuration", + "container", + "helper" + ], + "support": { + "issues": "https://github.com/chillerlan/php-settings-container/issues", + "source": "https://github.com/chillerlan/php-settings-container" + }, + "funding": [ + { + "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", + "type": "custom" + }, + { + "url": "https://ko-fi.com/codemasher", + "type": "ko_fi" + } + ], + "time": "2024-07-16T11:13:48+00:00" + }, { "name": "clue/stream-filter", "version": "v1.7.0", @@ -834,16 +864,16 @@ }, { "name": "composer/semver", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { @@ -895,7 +925,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" + "source": "https://github.com/composer/semver/tree/3.4.4" }, "funding": [ { @@ -905,13 +935,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2025-08-20T19:15:30+00:00" }, { "name": "danharrin/date-format-converter", @@ -1018,56 +1044,6 @@ ], "time": "2025-02-21T08:52:11+00:00" }, - { - "name": "dasprid/enum", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/DASPRiD/Enum.git", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90", - "shasum": "" - }, - "require": { - "php": ">=7.1 <9.0" - }, - "require-dev": { - "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", - "squizlabs/php_codesniffer": "*" - }, - "type": "library", - "autoload": { - "psr-4": { - "DASPRiD\\Enum\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Ben Scholzen 'DASPRiD'", - "email": "mail@dasprids.de", - "homepage": "https://dasprids.de/", - "role": "Developer" - } - ], - "description": "PHP 7.1 enum implementation", - "keywords": [ - "enum", - "map" - ], - "support": { - "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.6" - }, - "time": "2024-08-09T14:30:48+00:00" - }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -1144,45 +1120,33 @@ "time": "2024-07-08T12:26:09+00:00" }, { - "name": "doctrine/dbal", - "version": "4.3.1", + "name": "doctrine/inflector", + "version": "2.1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "ac336c95ea9e13433d56ca81c308b39db0e1a2a7" + "url": "https://github.com/doctrine/inflector.git", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/ac336c95ea9e13433d56ca81c308b39db0e1a2a7", - "reference": "ac336c95ea9e13433d56ca81c308b39db0e1a2a7", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.1.5", - "php": "^8.2", - "psr/cache": "^1|^2|^3", - "psr/log": "^1|^2|^3" + "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "13.0.0", - "fig/log-test": "^1", - "jetbrains/phpstorm-stubs": "2023.2", - "phpstan/phpstan": "2.1.17", - "phpstan/phpstan-phpunit": "2.0.6", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "11.5.23", - "slevomat/coding-standard": "8.16.2", - "squizlabs/php_codesniffer": "3.13.1", - "symfony/cache": "^6.3.8|^7.0", - "symfony/console": "^5.4|^6.3|^7.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\DBAL\\": "src" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1205,33 +1169,29 @@ { "name": "Jonathan Wage", "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlite", - "sqlserver", - "sqlsrv" + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" ], "support": { - "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.3.1" + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -1243,167 +1203,28 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", "type": "tidelift" } ], - "time": "2025-07-22T10:09:51+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { - "name": "doctrine/deprecations", - "version": "1.1.5", + "name": "doctrine/lexer", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", - "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", - "psr/log": "^1 || ^2 || ^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" - }, - "time": "2025-04-07T20:06:18+00:00" - }, - { - "name": "doctrine/inflector", - "version": "2.0.10", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", - "homepage": "https://www.doctrine-project.org/projects/inflector.html", - "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", - "php", - "plural", - "singular", - "strings", - "uppercase", - "words" - ], - "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", - "type": "tidelift" - } - ], - "time": "2024-02-18T20:23:39+00:00" - }, - { - "name": "doctrine/lexer", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "shasum": "" - }, - "require": { - "php": "^8.1" + "php": "^8.1" }, "require-dev": { "doctrine/coding-standard": "^12", @@ -1467,29 +1288,28 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" + "php": "^8.2|^8.3|^8.4|^8.5" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.32|^2.1.31", + "phpunit/phpunit": "^8.5.48|^9.0" }, "type": "library", "extra": { @@ -1520,7 +1340,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" }, "funding": [ { @@ -1528,7 +1348,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2025-10-31T18:51:33+00:00" }, { "name": "egulias/email-validator", @@ -1599,20 +1419,20 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.18.0", + "version": "v4.19.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b" + "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf", + "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -1654,22 +1474,22 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0" }, - "time": "2024-11-01T03:51:45+00:00" + "time": "2025-10-17T16:34:55+00:00" }, { "name": "filament/actions", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "9eaddc610d9adc00d738b8b116cea1be35a88f85" + "reference": "483fcb61b551cf524c943e75c4747c4aa2728bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/9eaddc610d9adc00d738b8b116cea1be35a88f85", - "reference": "9eaddc610d9adc00d738b8b116cea1be35a88f85", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/483fcb61b551cf524c943e75c4747c4aa2728bed", + "reference": "483fcb61b551cf524c943e75c4747c4aa2728bed", "shasum": "" }, "require": { @@ -1678,13 +1498,9 @@ "filament/infolists": "self.version", "filament/notifications": "self.version", "filament/support": "self.version", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/database": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "league/csv": "^9.16", + "league/csv": "^9.27", "openspout/openspout": "^4.23", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2" }, "type": "library", "extra": { @@ -1709,43 +1525,35 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-16T08:51:11+00:00" + "time": "2026-01-23T10:57:02+00:00" }, { "name": "filament/filament", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "8e6618036c9235d968740d43bb8afb58fe705e5b" + "reference": "7edac0aed33cac262766439f331cb1070ac974d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/8e6618036c9235d968740d43bb8afb58fe705e5b", - "reference": "8e6618036c9235d968740d43bb8afb58fe705e5b", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/7edac0aed33cac262766439f331cb1070ac974d5", + "reference": "7edac0aed33cac262766439f331cb1070ac974d5", "shasum": "" }, "require": { - "danharrin/livewire-rate-limiting": "^0.3|^1.0|^2.0", + "chillerlan/php-qrcode": "^5.0", "filament/actions": "self.version", "filament/forms": "self.version", "filament/infolists": "self.version", "filament/notifications": "self.version", + "filament/schemas": "self.version", "filament/support": "self.version", "filament/tables": "self.version", "filament/widgets": "self.version", - "illuminate/auth": "^10.45|^11.0|^12.0", - "illuminate/console": "^10.45|^11.0|^12.0", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/cookie": "^10.45|^11.0|^12.0", - "illuminate/database": "^10.45|^11.0|^12.0", - "illuminate/http": "^10.45|^11.0|^12.0", - "illuminate/routing": "^10.45|^11.0|^12.0", - "illuminate/session": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "illuminate/view": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2", + "pragmarx/google2fa": "^8.0|^9.0", + "pragmarx/google2fa-qrcode": "^3.0" }, "type": "library", "extra": { @@ -1774,35 +1582,29 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-21T10:08:08+00:00" + "time": "2026-01-23T10:54:16+00:00" }, { "name": "filament/forms", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "72ec2ede65d8e9fa979a066bce78812458793dde" + "reference": "847c1afe671bd3d5937eb0113413e581dd1ce019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/72ec2ede65d8e9fa979a066bce78812458793dde", - "reference": "72ec2ede65d8e9fa979a066bce78812458793dde", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/847c1afe671bd3d5937eb0113413e581dd1ce019", + "reference": "847c1afe671bd3d5937eb0113413e581dd1ce019", "shasum": "" }, "require": { "danharrin/date-format-converter": "^0.3", "filament/actions": "self.version", + "filament/schemas": "self.version", "filament/support": "self.version", - "illuminate/console": "^10.45|^11.0|^12.0", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/database": "^10.45|^11.0|^12.0", - "illuminate/filesystem": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "illuminate/validation": "^10.45|^11.0|^12.0", - "illuminate/view": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2", + "ueberdosis/tiptap-php": "^2.0" }, "type": "library", "extra": { @@ -1830,33 +1632,27 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-21T10:07:59+00:00" + "time": "2026-01-23T10:52:10+00:00" }, { "name": "filament/infolists", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "89a3f1f236863e2035be3d7b0c68987508dd06fa" + "reference": "841a0520637b98822f09d008509e040ba9ef3faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/89a3f1f236863e2035be3d7b0c68987508dd06fa", - "reference": "89a3f1f236863e2035be3d7b0c68987508dd06fa", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/841a0520637b98822f09d008509e040ba9ef3faa", + "reference": "841a0520637b98822f09d008509e040ba9ef3faa", "shasum": "" }, "require": { "filament/actions": "self.version", + "filament/schemas": "self.version", "filament/support": "self.version", - "illuminate/console": "^10.45|^11.0|^12.0", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/database": "^10.45|^11.0|^12.0", - "illuminate/filesystem": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "illuminate/view": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2" }, "type": "library", "extra": { @@ -1881,31 +1677,26 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-06-23T10:46:53+00:00" + "time": "2026-01-23T10:58:05+00:00" }, { "name": "filament/notifications", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "adc118c7fc34a423f3c01d6936ad0316f489949c" + "reference": "af01c113555d26ba73e75331ca19772b92a34dcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/adc118c7fc34a423f3c01d6936ad0316f489949c", - "reference": "adc118c7fc34a423f3c01d6936ad0316f489949c", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/af01c113555d26ba73e75331ca19772b92a34dcf", + "reference": "af01c113555d26ba73e75331ca19772b92a34dcf", "shasum": "" }, "require": { "filament/actions": "self.version", "filament/support": "self.version", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/filesystem": "^10.45|^11.0|^12.0", - "illuminate/notifications": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2" }, "type": "library", "extra": { @@ -1917,7 +1708,7 @@ }, "autoload": { "files": [ - "src/Testing/Autoload.php" + "src/Testing/helpers.php" ], "psr-4": { "Filament\\Notifications\\": "src" @@ -1933,27 +1724,117 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-08T20:42:18+00:00" + "time": "2026-01-23T10:54:41+00:00" + }, + { + "name": "filament/query-builder", + "version": "v4.6.0", + "source": { + "type": "git", + "url": "https://github.com/filamentphp/query-builder.git", + "reference": "bcafe9bb71ec34292440c4bded5ee395f037b2a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filamentphp/query-builder/zipball/bcafe9bb71ec34292440c4bded5ee395f037b2a5", + "reference": "bcafe9bb71ec34292440c4bded5ee395f037b2a5", + "shasum": "" + }, + "require": { + "filament/actions": "self.version", + "filament/forms": "self.version", + "filament/schemas": "self.version", + "filament/support": "self.version", + "php": "^8.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Filament\\QueryBuilder\\QueryBuilderServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Filament\\QueryBuilder\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A powerful query builder component for Filament.", + "homepage": "https://github.com/filamentphp/filament", + "support": { + "issues": "https://github.com/filamentphp/filament/issues", + "source": "https://github.com/filamentphp/filament" + }, + "time": "2026-01-23T10:52:35+00:00" + }, + { + "name": "filament/schemas", + "version": "v4.6.0", + "source": { + "type": "git", + "url": "https://github.com/filamentphp/schemas.git", + "reference": "4fd5207083308290c6fa14b34b9ade36c7e8d3d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filamentphp/schemas/zipball/4fd5207083308290c6fa14b34b9ade36c7e8d3d9", + "reference": "4fd5207083308290c6fa14b34b9ade36c7e8d3d9", + "shasum": "" + }, + "require": { + "danharrin/date-format-converter": "^0.3", + "filament/actions": "self.version", + "filament/support": "self.version", + "php": "^8.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Filament\\Schemas\\SchemasServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Filament\\Schemas\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Easily add beautiful UI to any Livewire component.", + "homepage": "https://github.com/filamentphp/filament", + "support": { + "issues": "https://github.com/filamentphp/filament/issues", + "source": "https://github.com/filamentphp/filament" + }, + "time": "2026-01-23T10:52:09+00:00" }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", - "reference": "bd7c12baf30cc66b2f088bd0257b12071e15addf" + "reference": "73748df28a9c2e8c34d2c02f9314c330602e1830" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-media-library-plugin/zipball/bd7c12baf30cc66b2f088bd0257b12071e15addf", - "reference": "bd7c12baf30cc66b2f088bd0257b12071e15addf", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-media-library-plugin/zipball/73748df28a9c2e8c34d2c02f9314c330602e1830", + "reference": "73748df28a9c2e8c34d2c02f9314c330602e1830", "shasum": "" }, "require": { "filament/support": "self.version", - "illuminate/support": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-medialibrary": "^10.0|^11.0" + "php": "^8.2", + "spatie/laravel-medialibrary": "^11.0" }, "type": "library", "autoload": { @@ -1971,38 +1852,37 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-08T20:42:14+00:00" + "time": "2025-12-09T09:54:02+00:00" }, { "name": "filament/support", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "0bf4856840e160624ba79f43aaaa3ec396140f1d" + "reference": "63698913952f41922f74d632c2dd9adff600bf7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/0bf4856840e160624ba79f43aaaa3ec396140f1d", - "reference": "0bf4856840e160624ba79f43aaaa3ec396140f1d", + "url": "https://api.github.com/repos/filamentphp/support/zipball/63698913952f41922f74d632c2dd9adff600bf7c", + "reference": "63698913952f41922f74d632c2dd9adff600bf7c", "shasum": "" }, "require": { "blade-ui-kit/blade-heroicons": "^2.5", - "doctrine/dbal": "^3.2|^4.0", + "danharrin/livewire-rate-limiting": "^2.0", "ext-intl": "*", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "illuminate/view": "^10.45|^11.0|^12.0", - "kirschbaum-development/eloquent-power-joins": "^3.0|^4.0", + "illuminate/contracts": "^11.28|^12.0", + "kirschbaum-development/eloquent-power-joins": "^4.0", + "league/uri-components": "^7.0", "livewire/livewire": "^3.5", - "php": "^8.1", - "ryangjchandler/blade-capture-directive": "^0.2|^0.3|^1.0", - "spatie/color": "^1.5", - "spatie/invade": "^1.0|^2.0", + "nette/php-generator": "^4.0", + "php": "^8.2", + "ryangjchandler/blade-capture-directive": "^1.0", + "spatie/invade": "^2.0", "spatie/laravel-package-tools": "^1.9", - "symfony/console": "^6.0|^7.0", - "symfony/html-sanitizer": "^6.1|^7.0" + "symfony/console": "^7.0", + "symfony/html-sanitizer": "^7.0" }, "type": "library", "extra": { @@ -2030,34 +1910,28 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-16T08:51:22+00:00" + "time": "2026-01-23T10:52:20+00:00" }, { "name": "filament/tables", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "3f0d827c960f1ee4a67ab71c416ad67e24747dc4" + "reference": "28107cc36098d86a4ac1511a3761bef7dc2cb986" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/3f0d827c960f1ee4a67ab71c416ad67e24747dc4", - "reference": "3f0d827c960f1ee4a67ab71c416ad67e24747dc4", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/28107cc36098d86a4ac1511a3761bef7dc2cb986", + "reference": "28107cc36098d86a4ac1511a3761bef7dc2cb986", "shasum": "" }, "require": { "filament/actions": "self.version", "filament/forms": "self.version", + "filament/query-builder": "self.version", "filament/support": "self.version", - "illuminate/console": "^10.45|^11.0|^12.0", - "illuminate/contracts": "^10.45|^11.0|^12.0", - "illuminate/database": "^10.45|^11.0|^12.0", - "illuminate/filesystem": "^10.45|^11.0|^12.0", - "illuminate/support": "^10.45|^11.0|^12.0", - "illuminate/view": "^10.45|^11.0|^12.0", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2" }, "type": "library", "extra": { @@ -2082,26 +1956,26 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-07-08T20:42:18+00:00" + "time": "2026-01-23T10:52:09+00:00" }, { "name": "filament/widgets", - "version": "v3.3.33", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "5b956f884aaef479f6091463cb829e7c9f2afc2c" + "reference": "2dfe6ea8d6a491cdf1eb7056561ec9db4b8cfeb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/5b956f884aaef479f6091463cb829e7c9f2afc2c", - "reference": "5b956f884aaef479f6091463cb829e7c9f2afc2c", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/2dfe6ea8d6a491cdf1eb7056561ec9db4b8cfeb2", + "reference": "2dfe6ea8d6a491cdf1eb7056561ec9db4b8cfeb2", "shasum": "" }, "require": { + "filament/schemas": "self.version", "filament/support": "self.version", - "php": "^8.1", - "spatie/laravel-package-tools": "^1.9" + "php": "^8.2" }, "type": "library", "extra": { @@ -2126,35 +2000,35 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2025-06-12T15:11:14+00:00" + "time": "2026-01-23T10:56:26+00:00" }, { "name": "fruitcake/php-cors", - "version": "v1.3.0", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6|^7" + "php": "^8.1", + "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" }, "require-dev": { - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -2185,7 +2059,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" }, "funding": [ { @@ -2197,28 +2071,28 @@ "type": "github" } ], - "time": "2023-10-12T05:21:21+00:00" + "time": "2025-12-03T09:33:47+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.3", + "version": "v1.1.4", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", + "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3" + "phpoption/phpoption": "^1.9.5" }, "require-dev": { - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" }, "type": "library", "autoload": { @@ -2247,7 +2121,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" }, "funding": [ { @@ -2259,26 +2133,26 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:45:45+00:00" + "time": "2025-12-27T19:43:20+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.9.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2369,7 +2243,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -2385,20 +2259,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:37:11+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -2406,7 +2280,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -2452,7 +2326,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.2.0" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -2468,20 +2342,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:27:01+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -2497,7 +2371,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2568,7 +2442,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -2584,20 +2458,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.4", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { @@ -2606,7 +2480,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", "uri-template/tests": "1.0.0" }, "type": "library", @@ -2654,7 +2528,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" }, "funding": [ { @@ -2670,32 +2544,43 @@ "type": "tidelift" } ], - "time": "2025-02-03T10:55:03+00:00" + "time": "2025-08-22T14:27:06+00:00" }, { - "name": "jaybizzle/crawler-detect", - "version": "v1.3.5", + "name": "jean85/pretty-package-versions", + "version": "2.1.1", "source": { "type": "git", - "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "fbf1a3e81d61b088e7af723fb3c7a4ee92ac7e34" + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/fbf1a3e81d61b088e7af723fb3c7a4ee92ac7e34", - "reference": "fbf1a3e81d61b088e7af723fb3c7a4ee92ac7e34", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", "shasum": "" }, "require": { - "php": ">=7.1.0" + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "rector/rector": "^2.0", + "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, "autoload": { "psr-4": { - "Jaybizzle\\CrawlerDetect\\": "src/" + "Jean85\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2704,74 +2589,11 @@ ], "authors": [ { - "name": "Mark Beech", - "email": "m@rkbee.ch", - "role": "Developer" + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" } ], - "description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent", - "homepage": "https://github.com/JayBizzle/Crawler-Detect/", - "keywords": [ - "crawler", - "crawler detect", - "crawler detector", - "crawlerdetect", - "php crawler detect" - ], - "support": { - "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", - "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.3.5" - }, - "time": "2025-06-11T17:58:05+00:00" - }, - { - "name": "jean85/pretty-package-versions", - "version": "2.1.1", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", - "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1.0", - "php": "^7.4|^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^7.5|^8.5|^9.6", - "rector/rector": "^2.0", - "vimeo/psalm": "^4.3 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A library to get pretty versions strings of installed dependencies", + "description": "A library to get pretty versions strings of installed dependencies", "keywords": [ "composer", "package", @@ -2784,224 +2606,18 @@ }, "time": "2025-03-19T14:43:43+00:00" }, - { - "name": "jeffgreco13/filament-breezy", - "version": "v2.6.4", - "source": { - "type": "git", - "url": "https://github.com/jeffgreco13/filament-breezy.git", - "reference": "3c59d37aaf907e97e02606c7bccb20bc62f71ecf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jeffgreco13/filament-breezy/zipball/3c59d37aaf907e97e02606c7bccb20bc62f71ecf", - "reference": "3c59d37aaf907e97e02606c7bccb20bc62f71ecf", - "shasum": "" - }, - "require": { - "bacon/bacon-qr-code": "^3.0", - "filament/filament": "^3.0.9", - "illuminate/contracts": "^10.0|^11.0|^12.0", - "jenssegers/agent": "^2.6", - "php": "^8.1|^8.2|^8.3|^8.4", - "pragmarx/google2fa": "^7.0|^8.0", - "spatie/laravel-package-tools": "^1.14.0" - }, - "require-dev": { - "pestphp/pest": "^2.20|^3.7", - "pestphp/pest-plugin-arch": "^2.0|^v3.0.0", - "pestphp/pest-plugin-laravel": "^2.0|^v3.1.0", - "pestphp/pest-plugin-livewire": "^2.1|^v3.0.0" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "FilamentBreezy": "Jeffgreco13\\FilamentBreezy\\Facades\\FilamentBreezy" - }, - "providers": [ - "Jeffgreco13\\FilamentBreezy\\FilamentBreezyServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Jeffgreco13\\FilamentBreezy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeff Greco", - "email": "jeff@jeffpgreco.com", - "role": "Developer" - } - ], - "description": "A custom package for Filament with login flow, profile and teams support.", - "homepage": "https://github.com/jeffgreco13/filament-breezy", - "keywords": [ - "filament-breezy", - "jeffgreco13", - "laravel" - ], - "support": { - "issues": "https://github.com/jeffgreco13/filament-breezy/issues", - "source": "https://github.com/jeffgreco13/filament-breezy/tree/v2.6.4" - }, - "time": "2025-06-09T17:18:54+00:00" - }, - { - "name": "jenssegers/agent", - "version": "v2.6.4", - "source": { - "type": "git", - "url": "https://github.com/jenssegers/agent.git", - "reference": "daa11c43729510b3700bc34d414664966b03bffe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jenssegers/agent/zipball/daa11c43729510b3700bc34d414664966b03bffe", - "reference": "daa11c43729510b3700bc34d414664966b03bffe", - "shasum": "" - }, - "require": { - "jaybizzle/crawler-detect": "^1.2", - "mobiledetect/mobiledetectlib": "^2.7.6", - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5.0|^6.0|^7.0" - }, - "suggest": { - "illuminate/support": "Required for laravel service providers" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Agent": "Jenssegers\\Agent\\Facades\\Agent" - }, - "providers": [ - "Jenssegers\\Agent\\AgentServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "Jenssegers\\Agent\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jens Segers", - "homepage": "https://jenssegers.com" - } - ], - "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", - "homepage": "https://github.com/jenssegers/agent", - "keywords": [ - "Agent", - "browser", - "desktop", - "laravel", - "mobile", - "platform", - "user agent", - "useragent" - ], - "support": { - "issues": "https://github.com/jenssegers/agent/issues", - "source": "https://github.com/jenssegers/agent/tree/v2.6.4" - }, - "funding": [ - { - "url": "https://github.com/jenssegers", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/jenssegers/agent", - "type": "tidelift" - } - ], - "time": "2020-06-13T08:05:20+00:00" - }, - { - "name": "kenepa/multi-widget", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/kenepa/multi-widget.git", - "reference": "813cc3cadcfd65979ff66fc58a38358b32f34b6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kenepa/multi-widget/zipball/813cc3cadcfd65979ff66fc58a38358b32f34b6f", - "reference": "813cc3cadcfd65979ff66fc58a38358b32f34b6f", - "shasum": "" - }, - "require": { - "filament/filament": "^3.0", - "php": "^8.0", - "spatie/laravel-package-tools": "^1.15.0" - }, - "require-dev": { - "tightenco/duster": "^2.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Kenepa\\MultiWidget\\MultiWidgetServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Kenepa\\MultiWidget\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A Filament widget that encompasses multiple widgets.", - "homepage": "https://github.com/kenepa/multi-widget", - "keywords": [ - "Kenepa", - "filament", - "laravel", - "multi-widget" - ], - "support": { - "issues": "https://github.com/kenepa/multi-widget/issues", - "source": "https://github.com/kenepa/multi-widget/tree/2.0.2" - }, - "abandoned": "vodafoneziggonl/filament-multi-widget", - "time": "2023-09-27T11:48:08+00:00" - }, { "name": "kirschbaum-development/eloquent-power-joins", - "version": "4.2.6", + "version": "4.2.11", "source": { "type": "git", "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "72cff1e838bb3f826dc09a5566219ad7fa56237f" + "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/72cff1e838bb3f826dc09a5566219ad7fa56237f", - "reference": "72cff1e838bb3f826dc09a5566219ad7fa56237f", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/0e3e3372992e4bf82391b3c7b84b435c3db73588", + "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588", "shasum": "" }, "require": { @@ -3049,26 +2665,26 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.2.6" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.2.11" }, - "time": "2025-07-10T16:55:34+00:00" + "time": "2025-12-17T00:37:48+00:00" }, { "name": "laravel/framework", - "version": "v11.45.1", + "version": "v12.48.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "b09ba32795b8e71df10856a2694706663984a239" + "reference": "0f0974a9769378ccd9c9935c09b9927f3a606830" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/b09ba32795b8e71df10856a2694706663984a239", - "reference": "b09ba32795b8e71df10856a2694706663984a239", + "url": "https://api.github.com/repos/laravel/framework/zipball/0f0974a9769378ccd9c9935c09b9927f3a606830", + "reference": "0f0974a9769378ccd9c9935c09b9927f3a606830", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.11|^0.12|^0.13|^0.14", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -3083,32 +2699,34 @@ "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", "league/commonmark": "^2.7", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.6|^3.8.4", + "nesbot/carbon": "^3.8.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.0.3", - "symfony/error-handler": "^7.0.3", - "symfony/finder": "^7.0.3", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", "symfony/http-foundation": "^7.2.0", - "symfony/http-kernel": "^7.0.3", - "symfony/mailer": "^7.0.3", - "symfony/mime": "^7.0.3", - "symfony/polyfill-php83": "^1.31", - "symfony/process": "^7.0.3", - "symfony/routing": "^7.0.3", - "symfony/uid": "^7.0.3", - "symfony/var-dumper": "^7.0.3", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/polyfill-php85": "^1.33", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.6.1", "voku/portable-ascii": "^2.0.2" @@ -3140,6 +2758,7 @@ "illuminate/filesystem": "self.version", "illuminate/hashing": "self.version", "illuminate/http": "self.version", + "illuminate/json-schema": "self.version", "illuminate/log": "self.version", "illuminate/macroable": "self.version", "illuminate/mail": "self.version", @@ -3149,6 +2768,7 @@ "illuminate/process": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", + "illuminate/reflection": "self.version", "illuminate/routing": "self.version", "illuminate/session": "self.version", "illuminate/support": "self.version", @@ -3172,17 +2792,18 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.13.2", - "pda/pheanstalk": "^5.0.6", + "opis/json-schema": "^2.4.1", + "orchestra/testbench-core": "^10.9.0", + "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", - "predis/predis": "^2.3", - "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.0.3", - "symfony/http-client": "^7.0.3", - "symfony/psr-http-message-bridge": "^7.0.3", - "symfony/translation": "^7.0.3" + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0|^1.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", @@ -3197,7 +2818,7 @@ "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", - "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", @@ -3208,22 +2829,22 @@ "mockery/mockery": "Required to use mocking (^1.6).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", - "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", - "predis/predis": "Required to use the predis connector (^2.3).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^7.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.0).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.0).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.0).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.0)." + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0|^1.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "12.x-dev" } }, "autoload": { @@ -3234,6 +2855,7 @@ "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Log/functions.php", + "src/Illuminate/Reflection/helpers.php", "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], @@ -3242,7 +2864,8 @@ "Illuminate\\Support\\": [ "src/Illuminate/Macroable/", "src/Illuminate/Collections/", - "src/Illuminate/Conditionable/" + "src/Illuminate/Conditionable/", + "src/Illuminate/Reflection/" ] } }, @@ -3266,20 +2889,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-06-03T14:01:40+00:00" + "time": "2026-01-20T16:12:36+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.6", + "version": "v0.3.10", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "86a8b692e8661d0fb308cec64f3d176821323077" + "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", - "reference": "86a8b692e8661d0fb308cec64f3d176821323077", + "url": "https://api.github.com/repos/laravel/prompts/zipball/360ba095ef9f51017473505191fbd4ab73e1cab3", + "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3", "shasum": "" }, "require": { @@ -3295,9 +2918,9 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" + "pestphp/pest": "^2.3|^3.4|^4.0", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -3323,22 +2946,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.6" + "source": "https://github.com/laravel/prompts/tree/v0.3.10" }, - "time": "2025-07-07T14:17:42+00:00" + "time": "2026-01-13T20:29:29+00:00" }, { "name": "laravel/sanctum", - "version": "v4.2.0", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677" + "reference": "dadd2277ff0f05cdb435c8b6a0bcedcf3b5519a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/dadd2277ff0f05cdb435c8b6a0bcedcf3b5519a9", + "reference": "dadd2277ff0f05cdb435c8b6a0bcedcf3b5519a9", "shasum": "" }, "require": { @@ -3352,9 +2975,8 @@ }, "require-dev": { "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^11.3" + "orchestra/testbench": "^9.15|^10.8", + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { @@ -3389,20 +3011,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2025-07-09T19:45:24+00:00" + "time": "2026-01-15T14:37:16+00:00" }, { "name": "laravel/scout", - "version": "v10.17.0", + "version": "v10.23.0", "source": { "type": "git", "url": "https://github.com/laravel/scout.git", - "reference": "66b064ab1f987560d1edfbc10f46557fddfed600" + "reference": "fb6d94cfc5708e4202dc00d46e61af0b9f35b03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/scout/zipball/66b064ab1f987560d1edfbc10f46557fddfed600", - "reference": "66b064ab1f987560d1edfbc10f46557fddfed600", + "url": "https://api.github.com/repos/laravel/scout/zipball/fb6d94cfc5708e4202dc00d46e61af0b9f35b03c", + "reference": "fb6d94cfc5708e4202dc00d46e61af0b9f35b03c", "shasum": "" }, "require": { @@ -3423,10 +3045,9 @@ "algolia/algoliasearch-client-php": "^3.2|^4.0", "meilisearch/meilisearch-php": "^1.0", "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.31|^8.11|^9.0|^10.0", + "orchestra/testbench": "^7.31|^8.36|^9.15|^10.8", "php-http/guzzle7-adapter": "^1.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.3|^10.4|^11.5", "typesense/typesense-php": "^4.9.3" }, "suggest": { @@ -3470,20 +3091,20 @@ "issues": "https://github.com/laravel/scout/issues", "source": "https://github.com/laravel/scout" }, - "time": "2025-07-22T15:54:45+00:00" + "time": "2025-12-16T15:43:03+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.4", + "version": "v2.0.8", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", - "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b", + "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b", "shasum": "" }, "require": { @@ -3492,7 +3113,7 @@ "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -3531,20 +3152,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-03-19T13:51:03+00:00" + "time": "2026-01-08T16:22:46+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.1", + "version": "v2.11.0", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "url": "https://api.github.com/repos/laravel/tinker/zipball/3d34b97c9a1747a81a3fde90482c092bd8b66468", + "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468", "shasum": "" }, "require": { @@ -3553,7 +3174,7 @@ "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^7.2.5|^8.0", "psy/psysh": "^0.11.1|^0.12.0", - "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0|^8.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", @@ -3595,22 +3216,22 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.1" + "source": "https://github.com/laravel/tinker/tree/v2.11.0" }, - "time": "2025-01-27T14:24:01+00:00" + "time": "2025-12-19T19:16:45+00:00" }, { "name": "league/commonmark", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", "shasum": "" }, "require": { @@ -3647,7 +3268,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.8-dev" + "dev-main": "2.9-dev" } }, "autoload": { @@ -3704,7 +3325,7 @@ "type": "tidelift" } ], - "time": "2025-07-20T12:47:49+00:00" + "time": "2025-11-26T21:48:24+00:00" }, { "name": "league/config", @@ -3790,16 +3411,16 @@ }, { "name": "league/csv", - "version": "9.24.1", + "version": "9.28.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8" + "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/e0221a3f16aa2a823047d59fab5809d552e29bc8", - "reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/6582ace29ae09ba5b07049d40ea13eb19c8b5073", + "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073", "shasum": "" }, "require": { @@ -3809,14 +3430,14 @@ "require-dev": { "ext-dom": "*", "ext-xdebug": "*", - "friendsofphp/php-cs-fixer": "^3.75.0", - "phpbench/phpbench": "^1.4.1", - "phpstan/phpstan": "^1.12.27", + "friendsofphp/php-cs-fixer": "^3.92.3", + "phpbench/phpbench": "^1.4.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-phpunit": "^1.4.2", "phpstan/phpstan-strict-rules": "^1.6.2", - "phpunit/phpunit": "^10.5.16 || ^11.5.22", - "symfony/var-dumper": "^6.4.8 || ^7.3.0" + "phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.5.4", + "symfony/var-dumper": "^6.4.8 || ^7.4.0 || ^8.0" }, "suggest": { "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", @@ -3877,20 +3498,20 @@ "type": "github" } ], - "time": "2025-06-25T14:53:51+00:00" + "time": "2025-12-27T15:18:42+00:00" }, { "name": "league/flysystem", - "version": "3.30.0", + "version": "3.31.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", - "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/1717e0b3642b0df65ecb0cc89cdd99fa840672ff", + "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff", "shasum": "" }, "require": { @@ -3958,22 +3579,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.31.0" }, - "time": "2025-06-25T13:29:59+00:00" + "time": "2026-01-23T15:38:47+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.29.0", + "version": "3.31.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" + "reference": "e36a2bc60b06332c92e4435047797ded352b446f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", - "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/e36a2bc60b06332c92e4435047797ded352b446f", + "reference": "e36a2bc60b06332c92e4435047797ded352b446f", "shasum": "" }, "require": { @@ -4013,22 +3634,22 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.31.0" }, - "time": "2024-08-17T13:10:48+00:00" + "time": "2026-01-23T15:30:45+00:00" }, { "name": "league/flysystem-local", - "version": "3.30.0", + "version": "3.31.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" + "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", - "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079", + "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079", "shasum": "" }, "require": { @@ -4062,9 +3683,9 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0" }, - "time": "2025-05-21T10:34:19+00:00" + "time": "2026-01-23T15:30:45+00:00" }, { "name": "league/mime-type-detection", @@ -4124,33 +3745,38 @@ }, { "name": "league/uri", - "version": "7.5.1", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "81fb5145d2644324614cc532b28efd0215bda430" + "reference": "4436c6ec8d458e4244448b069cc572d088230b76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", - "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", + "reference": "4436c6ec8d458e4244448b069cc572d088230b76", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.5", - "php": "^8.1" + "league/uri-interfaces": "^7.8", + "php": "^8.1", + "psr/http-factory": "^1" }, "conflict": { "league/uri-schemes": "^1.0" }, "suggest": { "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", "ext-fileinfo": "to create Data URI from file contennts", "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", - "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", - "league/uri-components": "Needed to easily manipulate URI objects components", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-components": "to provide additional tools to manipulate URI objects components", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -4178,6 +3804,7 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ + "URN", "data-uri", "file-uri", "ftp", @@ -4190,9 +3817,11 @@ "psr-7", "query-string", "querystring", + "rfc2141", "rfc3986", "rfc3987", "rfc6570", + "rfc8141", "uri", "uri-template", "url", @@ -4202,7 +3831,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.5.1" + "source": "https://github.com/thephpleague/uri/tree/7.8.0" }, "funding": [ { @@ -4210,26 +3839,109 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2026-01-14T17:24:56+00:00" + }, + { + "name": "league/uri-components", + "version": "7.8.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-components.git", + "reference": "8b5ffcebcc0842b76eb80964795bd56a8333b2ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/8b5ffcebcc0842b76eb80964795bd56a8333b2ba", + "reference": "8b5ffcebcc0842b76eb80964795bd56a8333b2ba", + "shasum": "" + }, + "require": { + "league/uri": "^7.8", + "php": "^8.1" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "ext-mbstring": "to use the sorting algorithm of URLSearchParams", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI components manipulation library", + "homepage": "http://uri.thephpleague.com", + "keywords": [ + "authority", + "components", + "fragment", + "host", + "middleware", + "modifier", + "path", + "port", + "query", + "rfc3986", + "scheme", + "uri", + "url", + "userinfo" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-components/tree/7.8.0" + }, + "funding": [ + { + "url": "https://github.com/nyamsprod", + "type": "github" + } + ], + "time": "2026-01-14T17:24:56+00:00" }, { "name": "league/uri-interfaces", - "version": "7.5.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", - "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -4237,6 +3949,7 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -4261,7 +3974,7 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common interfaces and classes for URI representation and interaction", + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", "homepage": "https://uri.thephpleague.com", "keywords": [ "data-uri", @@ -4286,7 +3999,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0" }, "funding": [ { @@ -4294,20 +4007,20 @@ "type": "github" } ], - "time": "2024-12-08T08:18:47+00:00" + "time": "2026-01-15T06:54:53+00:00" }, { "name": "livewire/livewire", - "version": "v3.6.4", + "version": "v3.7.6", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "ef04be759da41b14d2d129e670533180a44987dc" + "reference": "276ac156f6ae414990784854a2673e3d23c68b24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc", - "reference": "ef04be759da41b14d2d129e670533180a44987dc", + "url": "https://api.github.com/repos/livewire/livewire/zipball/276ac156f6ae414990784854a2673e3d23c68b24", + "reference": "276ac156f6ae414990784854a2673e3d23c68b24", "shasum": "" }, "require": { @@ -4362,7 +4075,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.6.4" + "source": "https://github.com/livewire/livewire/tree/v3.7.6" }, "funding": [ { @@ -4370,20 +4083,20 @@ "type": "github" } ], - "time": "2025-07-17T05:12:15+00:00" + "time": "2026-01-23T05:41:38+00:00" }, { "name": "maatwebsite/excel", - "version": "3.1.64", + "version": "3.1.67", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "e25d44a2d91da9179cd2d7fec952313548597a79" + "reference": "e508e34a502a3acc3329b464dad257378a7edb4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e25d44a2d91da9179cd2d7fec952313548597a79", - "reference": "e25d44a2d91da9179cd2d7fec952313548597a79", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d", + "reference": "e508e34a502a3acc3329b464dad257378a7edb4d", "shasum": "" }, "require": { @@ -4391,7 +4104,7 @@ "ext-json": "*", "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", "php": "^7.0||^8.0", - "phpoffice/phpspreadsheet": "^1.29.9", + "phpoffice/phpspreadsheet": "^1.30.0", "psr/simple-cache": "^1.0||^2.0||^3.0" }, "require-dev": { @@ -4439,7 +4152,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.64" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67" }, "funding": [ { @@ -4451,35 +4164,35 @@ "type": "github" } ], - "time": "2025-02-24T11:12:50+00:00" + "time": "2025-08-26T09:13:16+00:00" }, { "name": "maennchen/zipstream-php", - "version": "3.1.2", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/682f1098a8fddbaf43edac2306a691c7ad508ec5", + "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-zlib": "*", - "php-64bit": "^8.2" + "php-64bit": "^8.3" }, "require-dev": { "brianium/paratest": "^7.7", "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", + "friendsofphp/php-cs-fixer": "^3.86", "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^11.0", + "phpunit/phpunit": "^12.0", "vimeo/psalm": "^6.0" }, "suggest": { @@ -4521,7 +4234,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.1" }, "funding": [ { @@ -4529,7 +4242,7 @@ "type": "github" } ], - "time": "2025-01-27T12:07:53+00:00" + "time": "2025-12-10T09:58:31+00:00" }, { "name": "markbaker/complex", @@ -4640,16 +4353,16 @@ }, { "name": "masterminds/html5", - "version": "2.9.0", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + "reference": "fcf91eb64359852f00d921887b219479b4f21251" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", + "reference": "fcf91eb64359852f00d921887b219479b4f21251", "shasum": "" }, "require": { @@ -4701,84 +4414,22 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" }, - "time": "2024-03-31T07:05:07+00:00" + "time": "2025-07-25T09:04:22+00:00" }, { - "name": "mobiledetect/mobiledetectlib", - "version": "2.8.45", + "name": "monolog/monolog", + "version": "3.10.0", "source": { "type": "git", - "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266" + "url": "https://github.com/Seldaek/monolog.git", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/96aaebcf4f50d3d2692ab81d2c5132e425bca266", - "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266", - "shasum": "" - }, - "require": { - "php": ">=5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.36" - }, - "type": "library", - "autoload": { - "psr-0": { - "Detection": "namespaced/" - }, - "classmap": [ - "Mobile_Detect.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Serban Ghita", - "email": "serbanghita@gmail.com", - "homepage": "http://mobiledetect.net", - "role": "Developer" - } - ], - "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", - "homepage": "https://github.com/serbanghita/Mobile-Detect", - "keywords": [ - "detect mobile devices", - "mobile", - "mobile detect", - "mobile detector", - "php mobile detect" - ], - "support": { - "issues": "https://github.com/serbanghita/Mobile-Detect/issues", - "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.45" - }, - "funding": [ - { - "url": "https://github.com/serbanghita", - "type": "github" - } - ], - "time": "2023-11-07T21:57:25+00:00" - }, - { - "name": "monolog/monolog", - "version": "3.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", "shasum": "" }, "require": { @@ -4796,7 +4447,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", + "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -4856,7 +4507,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" }, "funding": [ { @@ -4868,7 +4519,7 @@ "type": "tidelift" } ], - "time": "2025-03-24T10:02:05+00:00" + "time": "2026-01-02T08:56:05+00:00" }, { "name": "mtdowling/jmespath.php", @@ -4938,16 +4589,16 @@ }, { "name": "nesbot/carbon", - "version": "3.10.1", + "version": "3.11.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00" + "reference": "bdb375400dcd162624531666db4799b36b64e4a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1fd1935b2d90aef2f093c5e35f7ae1257c448d00", - "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", + "reference": "bdb375400dcd162624531666db4799b36b64e4a1", "shasum": "" }, "require": { @@ -4955,9 +4606,9 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3.12 || ^7.0", + "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -4965,13 +4616,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.75.0", + "friendsofphp/php-cs-fixer": "^v3.87.1", "kylekatarnls/multi-tester": "^2.5.3", "phpmd/phpmd": "^2.15.0", "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.17", - "phpunit/phpunit": "^10.5.46", - "squizlabs/php_codesniffer": "^3.13.0" + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4" }, "bin": [ "bin/carbon" @@ -5039,29 +4690,101 @@ "type": "tidelift" } ], - "time": "2025-06-21T15:19:35+00:00" + "time": "2025-12-02T21:04:28+00:00" + }, + { + "name": "nette/php-generator", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.6", + "php": "8.1 - 8.5" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.4", + "nikic/php-parser": "^5.0", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.5 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "support": { + "issues": "https://github.com/nette/php-generator/issues", + "source": "https://github.com/nette/php-generator/tree/v4.2.0" + }, + "time": "2025-08-06T18:24:31+00:00" }, { "name": "nette/schema", - "version": "v1.3.2", + "version": "v1.3.3", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.4" + "php": "8.1 - 8.5" }, "require-dev": { "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^1.0", + "phpstan/phpstan-nette": "^2.0@stable", "tracy/tracy": "^2.8" }, "type": "library", @@ -5071,6 +4794,9 @@ } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -5099,35 +4825,35 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.2" + "source": "https://github.com/nette/schema/tree/v1.3.3" }, - "time": "2024-10-06T23:10:23+00:00" + "time": "2025-10-30T22:57:59+00:00" }, { "name": "nette/utils", - "version": "v4.0.7", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", - "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", "shasum": "" }, "require": { - "php": "8.0 - 8.4" + "php": "8.2 - 8.5" }, "conflict": { "nette/finder": "<3", "nette/schema": "<1.2.2" }, "require-dev": { - "jetbrains/phpstorm-attributes": "dev-master", + "jetbrains/phpstorm-attributes": "^1.2", "nette/tester": "^2.5", - "phpstan/phpstan": "^1.0", + "phpstan/phpstan-nette": "^2.0@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -5141,10 +4867,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -5185,22 +4914,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.7" + "source": "https://github.com/nette/utils/tree/v4.1.1" }, - "time": "2025-06-03T04:55:08+00:00" + "time": "2025-12-22T12:14:32+00:00" }, { "name": "nikic/php-parser", - "version": "v5.5.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -5219,7 +4948,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -5243,37 +4972,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-05-31T08:24:38+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.1", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", - "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.2.6" + "symfony/console": "^7.3.6" }, "require-dev": { - "illuminate/console": "^11.44.7", - "laravel/pint": "^1.22.0", + "illuminate/console": "^11.46.1", + "laravel/pint": "^1.25.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.2", - "phpstan/phpstan": "^1.12.25", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.2.6", + "symfony/var-dumper": "^7.3.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -5316,7 +5045,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" }, "funding": [ { @@ -5332,7 +5061,7 @@ "type": "github" } ], - "time": "2025-05-08T08:14:37+00:00" + "time": "2025-11-20T02:34:59+00:00" }, { "name": "nyholm/psr7", @@ -5414,16 +5143,16 @@ }, { "name": "openspout/openspout", - "version": "v4.28.5", + "version": "v4.32.0", "source": { "type": "git", "url": "https://github.com/openspout/openspout.git", - "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b" + "reference": "41f045c1f632e1474e15d4c7bc3abcb4a153563d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/openspout/openspout/zipball/ab05a09fe6fce57c90338f83280648a9786ce36b", - "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b", + "url": "https://api.github.com/repos/openspout/openspout/zipball/41f045c1f632e1474e15d4c7bc3abcb4a153563d", + "reference": "41f045c1f632e1474e15d4c7bc3abcb4a153563d", "shasum": "" }, "require": { @@ -5433,17 +5162,17 @@ "ext-libxml": "*", "ext-xmlreader": "*", "ext-zip": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "ext-zlib": "*", - "friendsofphp/php-cs-fixer": "^3.68.3", - "infection/infection": "^0.29.10", - "phpbench/phpbench": "^1.4.0", - "phpstan/phpstan": "^2.1.2", - "phpstan/phpstan-phpunit": "^2.0.4", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^11.5.4" + "friendsofphp/php-cs-fixer": "^3.86.0", + "infection/infection": "^0.31.2", + "phpbench/phpbench": "^1.4.1", + "phpstan/phpstan": "^2.1.22", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "phpunit/phpunit": "^12.3.7" }, "suggest": { "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", @@ -5491,7 +5220,7 @@ ], "support": { "issues": "https://github.com/openspout/openspout/issues", - "source": "https://github.com/openspout/openspout/tree/v4.28.5" + "source": "https://github.com/openspout/openspout/tree/v4.32.0" }, "funding": [ { @@ -5503,28 +5232,30 @@ "type": "github" } ], - "time": "2025-01-30T13:51:11+00:00" + "time": "2025-09-03T16:03:54+00:00" }, { "name": "paragonie/constant_time_encoding", - "version": "v3.0.0", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", "shasum": "" }, "require": { "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^9", - "vimeo/psalm": "^4|^5" + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" }, "type": "library", "autoload": { @@ -5570,20 +5301,20 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:36:18+00:00" + "time": "2025-09-24T15:06:41+00:00" }, { "name": "php-http/client-common", - "version": "2.7.2", + "version": "2.7.3", "source": { "type": "git", "url": "https://github.com/php-http/client-common.git", - "reference": "0cfe9858ab9d3b213041b947c881d5b19ceeca46" + "reference": "dcc6de29c90dd74faab55f71b79d89409c4bf0c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/client-common/zipball/0cfe9858ab9d3b213041b947c881d5b19ceeca46", - "reference": "0cfe9858ab9d3b213041b947c881d5b19ceeca46", + "url": "https://api.github.com/repos/php-http/client-common/zipball/dcc6de29c90dd74faab55f71b79d89409c4bf0c1", + "reference": "dcc6de29c90dd74faab55f71b79d89409c4bf0c1", "shasum": "" }, "require": { @@ -5593,15 +5324,13 @@ "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0 || ^2.0", - "symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0 || ^7.0", + "symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/polyfill-php80": "^1.17" }, "require-dev": { "doctrine/instantiator": "^1.1", "guzzlehttp/psr7": "^1.4", "nyholm/psr7": "^1.2", - "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", - "phpspec/prophecy": "^1.10.2", "phpunit/phpunit": "^7.5.20 || ^8.5.33 || ^9.6.7" }, "suggest": { @@ -5637,9 +5366,9 @@ ], "support": { "issues": "https://github.com/php-http/client-common/issues", - "source": "https://github.com/php-http/client-common/tree/2.7.2" + "source": "https://github.com/php-http/client-common/tree/2.7.3" }, - "time": "2024-09-24T06:21:48+00:00" + "time": "2025-11-29T19:12:34+00:00" }, { "name": "php-http/discovery", @@ -5900,16 +5629,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.29.11", + "version": "1.30.2", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "05b6c4378ddf3e81b460ea645c42b46432c0db25" + "reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/05b6c4378ddf3e81b460ea645c42b46432c0db25", - "reference": "05b6c4378ddf3e81b460ea645c42b46432c0db25", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/09cdde5e2f078b9a3358dd217e2c8cb4dac84be2", + "reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2", "shasum": "" }, "require": { @@ -5931,13 +5660,12 @@ "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", - "php": "^7.4 || ^8.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", + "php": ">=7.4.0 <8.5.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-main", + "doctrine/instantiator": "^1.5", "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", "friendsofphp/php-cs-fixer": "^3.2", "mitoteam/jpgraph": "^10.3", @@ -5984,6 +5712,9 @@ }, { "name": "Adrien Crivelli" + }, + { + "name": "Owen Leibman" } ], "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", @@ -6000,22 +5731,22 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.11" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.2" }, - "time": "2025-06-23T01:22:06+00:00" + "time": "2026-01-11T05:58:24+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", "shasum": "" }, "require": { @@ -6023,7 +5754,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" }, "type": "library", "extra": { @@ -6065,7 +5796,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" }, "funding": [ { @@ -6077,20 +5808,20 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" + "time": "2025-12-27T19:41:33+00:00" }, { "name": "pragmarx/google2fa", - "version": "v8.0.3", + "version": "v9.0.0", "source": { "type": "git", "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad" + "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/e6bc62dd6ae83acc475f57912e27466019a1f2cf", + "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf", "shasum": "" }, "require": { @@ -6127,36 +5858,49 @@ ], "support": { "issues": "https://github.com/antonioribeiro/google2fa/issues", - "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.3" + "source": "https://github.com/antonioribeiro/google2fa/tree/v9.0.0" }, - "time": "2024-09-05T11:56:40+00:00" + "time": "2025-09-19T22:51:08+00:00" }, { - "name": "psr/cache", - "version": "3.0.0", + "name": "pragmarx/google2fa-qrcode", + "version": "v3.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + "url": "https://github.com/antonioribeiro/google2fa-qrcode.git", + "reference": "ce4d8a729b6c93741c607cfb2217acfffb5bf76b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "url": "https://api.github.com/repos/antonioribeiro/google2fa-qrcode/zipball/ce4d8a729b6c93741c607cfb2217acfffb5bf76b", + "reference": "ce4d8a729b6c93741c607cfb2217acfffb5bf76b", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=7.1", + "pragmarx/google2fa": ">=4.0" + }, + "require-dev": { + "bacon/bacon-qr-code": "^2.0", + "chillerlan/php-qrcode": "^1.0|^2.0|^3.0|^4.0", + "khanamiryan/qrcode-detector-decoder": "^1.0", + "phpunit/phpunit": "~4|~5|~6|~7|~8|~9" + }, + "suggest": { + "bacon/bacon-qr-code": "For QR Code generation, requires imagick", + "chillerlan/php-qrcode": "For QR Code generation" }, "type": "library", "extra": { + "component": "package", "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "Psr\\Cache\\": "src/" + "PragmaRX\\Google2FAQRCode\\": "src/", + "PragmaRX\\Google2FAQRCode\\Tests\\": "tests/" } }, "notification-url": "https://packagist.org/downloads/", @@ -6165,20 +5909,25 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Antonio Carlos Ribeiro", + "email": "acr@antoniocarlosribeiro.com", + "role": "Creator & Designer" } ], - "description": "Common interface for caching libraries", + "description": "QR Code package for Google2FA", "keywords": [ - "cache", - "psr", - "psr-6" + "2fa", + "Authentication", + "Two Factor Authentication", + "google2fa", + "qr code", + "qrcode" ], "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" + "issues": "https://github.com/antonioribeiro/google2fa-qrcode/issues", + "source": "https://github.com/antonioribeiro/google2fa-qrcode/tree/v3.0.0" }, - "time": "2021-02-03T23:26:27+00:00" + "time": "2021-08-15T12:53:48+00:00" }, { "name": "psr/clock", @@ -6594,16 +6343,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.9", + "version": "v0.12.18", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "1b801844becfe648985372cb4b12ad6840245ace" + "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1b801844becfe648985372cb4b12ad6840245ace", - "reference": "1b801844becfe648985372cb4b12ad6840245ace", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ddff0ac01beddc251786fe70367cd8bbdb258196", + "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196", "shasum": "" }, "require": { @@ -6611,18 +6360,19 @@ "ext-tokenizer": "*", "nikic/php-parser": "^5.0 || ^4.0", "php": "^8.0 || ^7.4", - "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2" + "bamarni/composer-bin-plugin": "^1.2", + "composer/class-map-generator": "^1.6" }, "suggest": { + "composer/class-map-generator": "Improved tab completion performance with better class discovery.", "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ @@ -6653,12 +6403,11 @@ "authors": [ { "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" + "email": "justin@justinhileman.info" } ], "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", + "homepage": "https://psysh.org", "keywords": [ "REPL", "console", @@ -6667,76 +6416,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.9" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.18" }, - "time": "2025-06-23T02:35:06+00:00" - }, - { - "name": "pxlrbt/filament-excel", - "version": "v2.4.3", - "source": { - "type": "git", - "url": "https://github.com/pxlrbt/filament-excel.git", - "reference": "3425500cfede8a9334a6a79f001b5a36a117ca6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pxlrbt/filament-excel/zipball/3425500cfede8a9334a6a79f001b5a36a117ca6f", - "reference": "3425500cfede8a9334a6a79f001b5a36a117ca6f", - "shasum": "" - }, - "require": { - "anourvalar/eloquent-serialize": "^1.2", - "filament/filament": "^3.0.0-stable", - "maatwebsite/excel": "^3.1", - "php": "^8.1" - }, - "require-dev": { - "laravel/pint": "^1.10" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "pxlrbt\\FilamentExcel\\FilamentExcelServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "pxlrbt\\FilamentExcel\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Dennis Koch", - "email": "info@pixelarbeit.de" - } - ], - "description": "Supercharged Excel exports for Filament Resources", - "keywords": [ - "PHPExcel", - "actions", - "filament", - "laravel", - "laravel-filament", - "phpspreadsheet" - ], - "support": { - "issues": "https://github.com/pxlrbt/filament-excel/issues", - "source": "https://github.com/pxlrbt/filament-excel/tree/v2.4.3" - }, - "funding": [ - { - "url": "https://github.com/pxlrbt", - "type": "github" - } - ], - "time": "2025-03-22T02:12:15+00:00" + "time": "2025-12-17T14:35:46+00:00" }, { "name": "ralouphie/getallheaders", @@ -6860,20 +6542,20 @@ }, { "name": "ramsey/uuid", - "version": "4.9.0", + "version": "4.9.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" + "reference": "8429c78ca35a09f27565311b98101e2826affde0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", - "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", + "reference": "8429c78ca35a09f27565311b98101e2826affde0", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -6932,9 +6614,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.0" + "source": "https://github.com/ramsey/uuid/tree/4.9.2" }, - "time": "2025-06-25T14:20:11+00:00" + "time": "2025-12-14T04:43:48+00:00" }, { "name": "ryangjchandler/blade-capture-directive", @@ -7014,18 +6696,96 @@ ], "time": "2025-02-25T09:09:36+00:00" }, + { + "name": "scrivo/highlight.php", + "version": "v9.18.1.10", + "source": { + "type": "git", + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/850f4b44697a2552e892ffe71490ba2733c2fc6e", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.7", + "sabberworm/php-css-parser": "^8.3", + "symfony/finder": "^2.8|^3.4|^5.4", + "symfony/var-dumper": "^2.8|^3.4|^5.4" + }, + "suggest": { + "ext-mbstring": "Allows highlighting code with unicode characters and supports language with unicode keywords" + }, + "type": "library", + "autoload": { + "files": [ + "HighlightUtilities/functions.php" + ], + "psr-0": { + "Highlight\\": "", + "HighlightUtilities\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Geert Bergman", + "homepage": "http://www.scrivo.org/", + "role": "Project Author" + }, + { + "name": "Vladimir Jimenez", + "homepage": "https://allejo.io", + "role": "Maintainer" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Contributor" + } + ], + "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "support": { + "issues": "https://github.com/scrivo/highlight.php/issues", + "source": "https://github.com/scrivo/highlight.php" + }, + "funding": [ + { + "url": "https://github.com/allejo", + "type": "github" + } + ], + "time": "2022-12-17T21:53:22+00:00" + }, { "name": "sentry/sentry", - "version": "4.14.2", + "version": "4.19.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "bfeec74303d60d3f8bc33701ab3e86f8a8729f17" + "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/bfeec74303d60d3f8bc33701ab3e86f8a8729f17", - "reference": "bfeec74303d60d3f8bc33701ab3e86f8a8729f17", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/1c21d60bebe67c0122335bd3fe977990435af0a3", + "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3", "shasum": "" }, "require": { @@ -7036,7 +6796,7 @@ "jean85/pretty-package-versions": "^1.5|^2.0.4", "php": "^7.2|^8.0", "psr/log": "^1.0|^2.0|^3.0", - "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0" + "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0" }, "conflict": { "raven/raven": "*" @@ -7049,7 +6809,6 @@ "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^8.5|^9.6", - "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", "vimeo/psalm": "^4.17" }, "suggest": { @@ -7089,7 +6848,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.14.2" + "source": "https://github.com/getsentry/sentry-php/tree/4.19.1" }, "funding": [ { @@ -7101,34 +6860,35 @@ "type": "custom" } ], - "time": "2025-07-21T08:28:29+00:00" + "time": "2025-12-02T15:57:41+00:00" }, { "name": "sentry/sentry-laravel", - "version": "4.15.1", + "version": "4.20.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5" + "reference": "503853fa7ee74b34b64e76f1373db86cd11afe72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/7e0675e8e06d1ec5cb623792892920000a3aedb5", - "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/503853fa7ee74b34b64e76f1373db86cd11afe72", + "reference": "503853fa7ee74b34b64e76f1373db86cd11afe72", "shasum": "" }, "require": { "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", - "sentry/sentry": "^4.14.1", - "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0" + "sentry/sentry": "^4.19.0", + "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0 | ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.11", "guzzlehttp/guzzle": "^7.2", "laravel/folio": "^1.1", "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", + "laravel/pennant": "^1.0", "livewire/livewire": "^2.0 | ^3.0", "mockery/mockery": "^1.3", "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", @@ -7178,7 +6938,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/4.15.1" + "source": "https://github.com/getsentry/sentry-laravel/tree/4.20.1" }, "funding": [ { @@ -7190,33 +6950,46 @@ "type": "custom" } ], - "time": "2025-06-24T12:39:03+00:00" + "time": "2026-01-07T08:53:19+00:00" }, { - "name": "spatie/color", - "version": "1.8.0", + "name": "spatie/image", + "version": "3.9.1", "source": { "type": "git", - "url": "https://github.com/spatie/color.git", - "reference": "142af7fec069a420babea80a5412eb2f646dcd8c" + "url": "https://github.com/spatie/image.git", + "reference": "9a8e02839897b236f37708d24bcb12381ba050ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/color/zipball/142af7fec069a420babea80a5412eb2f646dcd8c", - "reference": "142af7fec069a420babea80a5412eb2f646dcd8c", + "url": "https://api.github.com/repos/spatie/image/zipball/9a8e02839897b236f37708d24bcb12381ba050ff", + "reference": "9a8e02839897b236f37708d24bcb12381ba050ff", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "ext-exif": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.2", + "spatie/image-optimizer": "^1.7.5", + "spatie/temporary-directory": "^2.2", + "symfony/process": "^6.4|^7.0|^8.0" }, "require-dev": { - "pestphp/pest": "^1.22", - "phpunit/phpunit": "^6.5||^9.0" + "ext-gd": "*", + "ext-imagick": "*", + "laravel/sail": "^1.34", + "pestphp/pest": "^3.0|^4.0", + "phpstan/phpstan": "^1.10.50", + "spatie/pest-plugin-snapshots": "^2.1", + "spatie/pixelmatch-php": "^1.0", + "spatie/ray": "^1.40.1", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Spatie\\Color\\": "src" + "Spatie\\Image\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -7225,129 +6998,57 @@ ], "authors": [ { - "name": "Sebastian De Deyne", - "email": "sebastian@spatie.be", + "name": "Freek Van der Herten", + "email": "freek@spatie.be", "homepage": "https://spatie.be", "role": "Developer" } ], - "description": "A little library to handle color conversions", - "homepage": "https://github.com/spatie/color", + "description": "Manipulate images with an expressive API", + "homepage": "https://github.com/spatie/image", "keywords": [ - "color", - "conversion", - "rgb", + "image", "spatie" ], "support": { - "issues": "https://github.com/spatie/color/issues", - "source": "https://github.com/spatie/color/tree/1.8.0" + "source": "https://github.com/spatie/image/tree/3.9.1" }, "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, { "url": "https://github.com/spatie", "type": "github" } ], - "time": "2025-02-10T09:22:41+00:00" + "time": "2026-01-12T07:34:13+00:00" }, { - "name": "spatie/image", - "version": "3.8.5", + "name": "spatie/image-optimizer", + "version": "1.8.1", "source": { "type": "git", - "url": "https://github.com/spatie/image.git", - "reference": "a63f60b7387ebeacab463e79a95deb7ffed75430" + "url": "https://github.com/spatie/image-optimizer.git", + "reference": "2ad9ac7c19501739183359ae64ea6c15869c23d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/image/zipball/a63f60b7387ebeacab463e79a95deb7ffed75430", - "reference": "a63f60b7387ebeacab463e79a95deb7ffed75430", - "shasum": "" - }, - "require": { - "ext-exif": "*", - "ext-json": "*", - "ext-mbstring": "*", - "php": "^8.2", - "spatie/image-optimizer": "^1.7.5", - "spatie/temporary-directory": "^2.2", - "symfony/process": "^6.4|^7.0" - }, - "require-dev": { - "ext-gd": "*", - "ext-imagick": "*", - "laravel/sail": "^1.34", - "pestphp/pest": "^2.28", - "phpstan/phpstan": "^1.10.50", - "spatie/pest-plugin-snapshots": "^2.1", - "spatie/pixelmatch-php": "^1.0", - "spatie/ray": "^1.40.1", - "symfony/var-dumper": "^6.4|7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Spatie\\Image\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://spatie.be", - "role": "Developer" - } - ], - "description": "Manipulate images with an expressive API", - "homepage": "https://github.com/spatie/image", - "keywords": [ - "image", - "spatie" - ], - "support": { - "source": "https://github.com/spatie/image/tree/3.8.5" - }, - "funding": [ - { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - }, - { - "url": "https://github.com/spatie", - "type": "github" - } - ], - "time": "2025-06-27T12:44:55+00:00" - }, - { - "name": "spatie/image-optimizer", - "version": "1.8.0", - "source": { - "type": "git", - "url": "https://github.com/spatie/image-optimizer.git", - "reference": "4fd22035e81d98fffced65a8c20d9ec4daa9671c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/4fd22035e81d98fffced65a8c20d9ec4daa9671c", - "reference": "4fd22035e81d98fffced65a8c20d9ec4daa9671c", + "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/2ad9ac7c19501739183359ae64ea6c15869c23d9", + "reference": "2ad9ac7c19501739183359ae64ea6c15869c23d9", "shasum": "" }, "require": { "ext-fileinfo": "*", "php": "^7.3|^8.0", "psr/log": "^1.0 | ^2.0 | ^3.0", - "symfony/process": "^4.2|^5.0|^6.0|^7.0" + "symfony/process": "^4.2|^5.0|^6.0|^7.0|^8.0" }, "require-dev": { - "pestphp/pest": "^1.21", - "phpunit/phpunit": "^8.5.21|^9.4.4", - "symfony/var-dumper": "^4.2|^5.0|^6.0|^7.0" + "pestphp/pest": "^1.21|^2.0|^3.0|^4.0", + "phpunit/phpunit": "^8.5.21|^9.4.4|^10.0|^11.0|^12.0", + "symfony/var-dumper": "^4.2|^5.0|^6.0|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7375,9 +7076,9 @@ ], "support": { "issues": "https://github.com/spatie/image-optimizer/issues", - "source": "https://github.com/spatie/image-optimizer/tree/1.8.0" + "source": "https://github.com/spatie/image-optimizer/tree/1.8.1" }, - "time": "2024-11-04T08:24:54+00:00" + "time": "2025-11-26T10:57:19+00:00" }, { "name": "spatie/invade", @@ -7531,16 +7232,16 @@ }, { "name": "spatie/laravel-medialibrary", - "version": "11.13.0", + "version": "11.17.10", "source": { "type": "git", "url": "https://github.com/spatie/laravel-medialibrary.git", - "reference": "e2324b2f138ec41181089a7dcf28489be93ede53" + "reference": "10bbf232d27a69fd2f991e88d7e3d72e84d715cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/e2324b2f138ec41181089a7dcf28489be93ede53", - "reference": "e2324b2f138ec41181089a7dcf28489be93ede53", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/10bbf232d27a69fd2f991e88d7e3d72e84d715cb", + "reference": "10bbf232d27a69fd2f991e88d7e3d72e84d715cb", "shasum": "" }, "require": { @@ -7559,7 +7260,7 @@ "spatie/image": "^3.3.2", "spatie/laravel-package-tools": "^1.16.1", "spatie/temporary-directory": "^2.2", - "symfony/console": "^6.4.1|^7.0" + "symfony/console": "^6.4.1|^7.0|^8.0" }, "conflict": { "php-ffmpeg/php-ffmpeg": "<0.6.1" @@ -7573,11 +7274,12 @@ "larastan/larastan": "^2.7|^3.0", "league/flysystem-aws-s3-v3": "^3.22", "mockery/mockery": "^1.6.7", - "orchestra/testbench": "^7.0|^8.17|^9.0|^10.0", - "pestphp/pest": "^2.28|^3.5", + "orchestra/testbench": "^8.36|^9.15|^10.8", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/extension-installer": "^1.3.1", "spatie/laravel-ray": "^1.33", "spatie/pdf-to-image": "^2.2|^3.0", + "spatie/pest-expectations": "^1.13", "spatie/pest-plugin-snapshots": "^2.1" }, "suggest": { @@ -7624,7 +7326,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-medialibrary/issues", - "source": "https://github.com/spatie/laravel-medialibrary/tree/11.13.0" + "source": "https://github.com/spatie/laravel-medialibrary/tree/11.17.10" }, "funding": [ { @@ -7636,7 +7338,7 @@ "type": "github" } ], - "time": "2025-05-22T12:25:27+00:00" + "time": "2026-01-22T23:17:57+00:00" }, { "name": "spatie/laravel-package-tools", @@ -7699,18 +7401,83 @@ ], "time": "2025-07-17T15:46:43+00:00" }, + { + "name": "spatie/shiki-php", + "version": "2.3.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/shiki-php.git", + "reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/shiki-php/zipball/a2e78a9ff8a1290b25d550be8fbf8285c13175c5", + "reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.0", + "symfony/process": "^5.4|^6.4|^7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v3.0", + "pestphp/pest": "^1.8", + "phpunit/phpunit": "^9.5", + "spatie/pest-plugin-snapshots": "^1.1", + "spatie/ray": "^1.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ShikiPhp\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rias Van der Veken", + "email": "rias@spatie.be", + "role": "Developer" + }, + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Highlight code using Shiki in PHP", + "homepage": "https://github.com/spatie/shiki-php", + "keywords": [ + "shiki", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/shiki-php/tree/2.3.2" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-02-21T14:16:57+00:00" + }, { "name": "spatie/temporary-directory", - "version": "2.3.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b" + "reference": "662e481d6ec07ef29fd05010433428851a42cd07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/580eddfe9a0a41a902cac6eeb8f066b42e65a32b", - "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/662e481d6ec07ef29fd05010433428851a42cd07", + "reference": "662e481d6ec07ef29fd05010433428851a42cd07", "shasum": "" }, "require": { @@ -7746,7 +7513,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.3.0" + "source": "https://github.com/spatie/temporary-directory/tree/2.3.1" }, "funding": [ { @@ -7758,32 +7525,32 @@ "type": "github" } ], - "time": "2025-01-13T13:04:43+00:00" + "time": "2026-01-12T07:42:22+00:00" }, { "name": "staudenmeir/belongs-to-through", - "version": "v2.16.4", + "version": "v2.17", "source": { "type": "git", "url": "https://github.com/staudenmeir/belongs-to-through.git", - "reference": "451496e4272c11d87b404791acdd352c606f29c0" + "reference": "e45460f8eecd882e5daea2af8f948d7596c20ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staudenmeir/belongs-to-through/zipball/451496e4272c11d87b404791acdd352c606f29c0", - "reference": "451496e4272c11d87b404791acdd352c606f29c0", + "url": "https://api.github.com/repos/staudenmeir/belongs-to-through/zipball/e45460f8eecd882e5daea2af8f948d7596c20ba0", + "reference": "e45460f8eecd882e5daea2af8f948d7596c20ba0", "shasum": "" }, "require": { - "illuminate/database": "^11.0", + "illuminate/database": "^12.0", "php": "^8.2" }, "require-dev": { "barryvdh/laravel-ide-helper": "^3.0", "larastan/larastan": "^3.0", - "laravel/framework": "^11.0", + "laravel/framework": "^12.0", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^9.5", + "orchestra/testbench-core": "^10.0", "phpunit/phpunit": "^11.0" }, "type": "library", @@ -7817,7 +7584,7 @@ "description": "Laravel Eloquent BelongsToThrough relationships", "support": { "issues": "https://github.com/staudenmeir/belongs-to-through/issues", - "source": "https://github.com/staudenmeir/belongs-to-through/tree/v2.16.4" + "source": "https://github.com/staudenmeir/belongs-to-through/tree/v2.17" }, "funding": [ { @@ -7825,38 +7592,38 @@ "type": "custom" } ], - "time": "2025-02-20T19:20:43+00:00" + "time": "2025-02-20T19:24:03+00:00" }, { "name": "staudenmeir/eloquent-has-many-deep", - "version": "v1.20.7", + "version": "v1.21.2", "source": { "type": "git", "url": "https://github.com/staudenmeir/eloquent-has-many-deep.git", - "reference": "52155a1ac051e0c451f329937e591f9b892f05e2" + "reference": "b0a3041c44237ebcd0d1005e475a4c736cba482c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep/zipball/52155a1ac051e0c451f329937e591f9b892f05e2", - "reference": "52155a1ac051e0c451f329937e591f9b892f05e2", + "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep/zipball/b0a3041c44237ebcd0d1005e475a4c736cba482c", + "reference": "b0a3041c44237ebcd0d1005e475a4c736cba482c", "shasum": "" }, "require": { - "illuminate/database": "^11.0", + "illuminate/database": "^12.0", "php": "^8.2", - "staudenmeir/eloquent-has-many-deep-contracts": "^1.2" + "staudenmeir/eloquent-has-many-deep-contracts": "^1.3" }, "require-dev": { "awobaz/compoships": "^2.3", "barryvdh/laravel-ide-helper": "^3.0", - "korridor/laravel-has-many-merged": "^1.1", + "korridor/laravel-has-many-merged": "^1.2", "larastan/larastan": "^3.0", - "laravel/framework": "^11.0", + "laravel/framework": "^12.0", "mockery/mockery": "^1.6", - "orchestra/testbench-core": "^9.5", + "orchestra/testbench-core": "^10.0", "phpunit/phpunit": "^11.0", - "staudenmeir/eloquent-json-relations": "^1.11", - "staudenmeir/laravel-adjacency-list": "^1.21" + "staudenmeir/eloquent-json-relations": "^1.14", + "staudenmeir/laravel-adjacency-list": "^1.24" }, "type": "library", "extra": { @@ -7884,7 +7651,7 @@ "description": "Laravel Eloquent HasManyThrough relationships with unlimited levels", "support": { "issues": "https://github.com/staudenmeir/eloquent-has-many-deep/issues", - "source": "https://github.com/staudenmeir/eloquent-has-many-deep/tree/v1.20.7" + "source": "https://github.com/staudenmeir/eloquent-has-many-deep/tree/v1.21.2" }, "funding": [ { @@ -7892,24 +7659,24 @@ "type": "custom" } ], - "time": "2025-02-16T14:39:47+00:00" + "time": "2025-11-08T08:44:24+00:00" }, { "name": "staudenmeir/eloquent-has-many-deep-contracts", - "version": "v1.2.1", + "version": "v1.3", "source": { "type": "git", "url": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts.git", - "reference": "3ad76c6eeda60042f262d113bf471dcce584d88b" + "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep-contracts/zipball/3ad76c6eeda60042f262d113bf471dcce584d88b", - "reference": "3ad76c6eeda60042f262d113bf471dcce584d88b", + "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep-contracts/zipball/37ce351e4db919b3af606bc8ca0e62e2e4939cde", + "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde", "shasum": "" }, "require": { - "illuminate/database": "^11.0", + "illuminate/database": "^12.0", "php": "^8.2" }, "type": "library", @@ -7931,9 +7698,9 @@ "description": "Contracts for staudenmeir/eloquent-has-many-deep", "support": { "issues": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/issues", - "source": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/tree/v1.2.1" + "source": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/tree/v1.3" }, - "time": "2024-09-25T18:24:22+00:00" + "time": "2025-02-15T17:11:01+00:00" }, { "name": "stevegrunwell/time-constants", @@ -7982,22 +7749,21 @@ }, { "name": "symfony/clock", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "php": ">=8.4", + "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -8036,7 +7802,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.3.0" + "source": "https://github.com/symfony/clock/tree/v8.0.0" }, "funding": [ { @@ -8047,25 +7813,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-11-12T15:46:48+00:00" }, { "name": "symfony/console", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", + "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", "shasum": "" }, "require": { @@ -8073,7 +7843,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -8087,16 +7857,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -8130,7 +7900,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.1" + "source": "https://github.com/symfony/console/tree/v7.4.4" }, "funding": [ { @@ -8141,29 +7911,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2026-01-13T11:36:38+00:00" }, { "name": "symfony/css-selector", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + "reference": "6225bd458c53ecdee056214cb4a2ffaf58bd592b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/6225bd458c53ecdee056214cb4a2ffaf58bd592b", + "reference": "6225bd458c53ecdee056214cb4a2ffaf58bd592b", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "type": "library", "autoload": { @@ -8195,7 +7969,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + "source": "https://github.com/symfony/css-selector/tree/v8.0.0" }, "funding": [ { @@ -8206,12 +7980,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-10-30T14:17:19+00:00" }, { "name": "symfony/deprecation-contracts", @@ -8282,32 +8060,33 @@ }, { "name": "symfony/error-handler", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235" + "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/35b55b166f6752d6aaf21aa042fc5ed280fce235", - "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -8339,7 +8118,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.3.1" + "source": "https://github.com/symfony/error-handler/tree/v7.4.4" }, "funding": [ { @@ -8350,33 +8129,37 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-13T07:48:40+00:00" + "time": "2026-01-20T16:42:42+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.3.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -8385,13 +8168,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -8419,7 +8203,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4" }, "funding": [ { @@ -8430,12 +8214,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-22T09:11:45+00:00" + "time": "2026-01-05T11:45:55+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -8513,25 +8301,95 @@ ], "time": "2024-09-25T14:21:43+00:00" }, + { + "name": "symfony/filesystem", + "version": "v8.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "d937d400b980523dc9ee946bb69972b5e619058d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", + "reference": "d937d400b980523dc9ee946bb69972b5e619058d", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v8.0.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-01T09:13:36+00:00" + }, { "name": "symfony/finder", - "version": "v7.3.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" + "reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", - "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", + "url": "https://api.github.com/repos/symfony/finder/zipball/01b24a145bbeaa7141e75887ec904c34a6728a5f", + "reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -8559,7 +8417,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.0" + "source": "https://github.com/symfony/finder/tree/v7.4.4" }, "funding": [ { @@ -8570,32 +8428,37 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-30T19:00:26+00:00" + "time": "2026-01-12T12:19:02+00:00" }, { "name": "symfony/html-sanitizer", - "version": "v7.3.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/html-sanitizer.git", - "reference": "cf21254e982b12276329940ca4af5e623ee06c58" + "reference": "5b0bbcc3600030b535dd0b17a0e8c56243f96d7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/cf21254e982b12276329940ca4af5e623ee06c58", - "reference": "cf21254e982b12276329940ca4af5e623ee06c58", + "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/5b0bbcc3600030b535dd0b17a0e8c56243f96d7f", + "reference": "5b0bbcc3600030b535dd0b17a0e8c56243f96d7f", "shasum": "" }, "require": { "ext-dom": "*", "league/uri": "^6.5|^7.0", "masterminds/html5": "^2.7.2", - "php": ">=8.2" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -8628,7 +8491,7 @@ "sanitizer" ], "support": { - "source": "https://github.com/symfony/html-sanitizer/tree/v7.3.0" + "source": "https://github.com/symfony/html-sanitizer/tree/v7.4.0" }, "funding": [ { @@ -8639,32 +8502,35 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-03-31T08:49:55+00:00" + "time": "2025-10-30T13:39:42+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "23dd60256610c86a3414575b70c596e5deff6ed9" + "reference": "977a554a34cf8edc95ca351fbecb1bb1ad05cc94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/23dd60256610c86a3414575b70c596e5deff6ed9", - "reference": "23dd60256610c86a3414575b70c596e5deff6ed9", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/977a554a34cf8edc95ca351fbecb1bb1ad05cc94", + "reference": "977a554a34cf8edc95ca351fbecb1bb1ad05cc94", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { "doctrine/dbal": "<3.6", @@ -8673,13 +8539,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/clock": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^6.4.12|^7.1.5|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -8707,7 +8573,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.1" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.4" }, "funding": [ { @@ -8718,34 +8584,38 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-23T15:07:14+00:00" + "time": "2026-01-09T12:14:21+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "1644879a66e4aa29c36fe33dfa6c54b450ce1831" + "reference": "48b067768859f7b68acf41dfb857a5a4be00acdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1644879a66e4aa29c36fe33dfa6c54b450ce1831", - "reference": "1644879a66e4aa29c36fe33dfa6c54b450ce1831", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/48b067768859f7b68acf41dfb857a5a4be00acdd", + "reference": "48b067768859f7b68acf41dfb857a5a4be00acdd", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -8755,6 +8625,7 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", + "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -8772,27 +8643,27 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^7.1|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.1|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "type": "library", @@ -8821,7 +8692,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.1" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.4" }, "funding": [ { @@ -8832,25 +8703,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-28T08:24:55+00:00" + "time": "2026-01-24T22:13:01+00:00" }, { "name": "symfony/mailer", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368" + "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/b5db5105b290bdbea5ab27b89c69effcf1cb3368", - "reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368", + "url": "https://api.github.com/repos/symfony/mailer/zipball/7b750074c40c694ceb34cb926d6dffee231c5cd6", + "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6", "shasum": "" }, "require": { @@ -8858,8 +8733,8 @@ "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^7.2", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.2|^8.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -8870,10 +8745,10 @@ "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -8901,7 +8776,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.1" + "source": "https://github.com/symfony/mailer/tree/v7.4.4" }, "funding": [ { @@ -8912,29 +8787,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2026-01-08T08:25:11+00:00" }, { "name": "symfony/mime", - "version": "v7.3.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" + "reference": "40945014c0a9471ccfe19673c54738fa19367a3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", - "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "url": "https://api.github.com/repos/symfony/mime/zipball/40945014c0a9471ccfe19673c54738fa19367a3c", + "reference": "40945014c0a9471ccfe19673c54738fa19367a3c", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -8949,11 +8829,11 @@ "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0" }, "type": "library", "autoload": { @@ -8985,7 +8865,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.3.0" + "source": "https://github.com/symfony/mime/tree/v7.4.4" }, "funding": [ { @@ -8996,29 +8876,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-02-19T08:51:26+00:00" + "time": "2026-01-08T16:12:55+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", - "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -9052,7 +8936,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" + "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" }, "funding": [ { @@ -9063,16 +8947,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-04T13:12:05+00:00" + "time": "2025-11-12T15:55:31+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -9131,7 +9019,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -9142,6 +9030,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -9151,16 +9043,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -9209,7 +9101,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -9220,16 +9112,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -9237,16 +9133,191 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", - "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.2", - "symfony/polyfill-intl-normalizer": "^1.10" + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" }, "suggest": { - "ext-intl": "For best performance" + "ext-mbstring": "For best performance" }, "type": "library", "extra": { @@ -9260,7 +9331,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" + "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -9269,30 +9340,25 @@ ], "authors": [ { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "idn", - "intl", + "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -9303,33 +9369,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-10T14:38:51+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "name": "symfony/polyfill-php80", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { "php": ">=7.2" }, - "suggest": { - "ext-intl": "For best performance" - }, "type": "library", "extra": { "thanks": { @@ -9342,7 +9409,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -9353,6 +9420,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -9362,18 +9433,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "intl", - "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -9384,37 +9453,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "name": "symfony/polyfill-php83", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", "shasum": "" }, "require": { - "ext-iconv": "*", "php": ">=7.2" }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, "type": "library", "extra": { "thanks": { @@ -9427,8 +9493,11 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -9444,17 +9513,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -9465,25 +9533,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2025-07-08T02:45:35+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.32.0", + "name": "symfony/polyfill-php84", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", "shasum": "" }, "require": { @@ -9501,7 +9573,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php84\\": "" }, "classmap": [ "Resources/stubs" @@ -9512,10 +9584,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -9525,7 +9593,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -9534,7 +9602,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" }, "funding": [ { @@ -9545,25 +9613,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2025-06-24T13:30:11+00:00" }, { - "name": "symfony/polyfill-php83", - "version": "v1.32.0", + "name": "symfony/polyfill-php85", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", "shasum": "" }, "require": { @@ -9581,7 +9653,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" + "Symfony\\Polyfill\\Php85\\": "" }, "classmap": [ "Resources/stubs" @@ -9601,7 +9673,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -9610,7 +9682,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" }, "funding": [ { @@ -9621,16 +9693,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-23T16:12:55+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -9689,7 +9765,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" }, "funding": [ { @@ -9700,6 +9776,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -9709,16 +9789,16 @@ }, { "name": "symfony/process", - "version": "v7.3.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + "reference": "626f07a53f4b4e2f00e11824cc29f928d797783b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "url": "https://api.github.com/repos/symfony/process/zipball/626f07a53f4b4e2f00e11824cc29f928d797783b", + "reference": "626f07a53f4b4e2f00e11824cc29f928d797783b", "shasum": "" }, "require": { @@ -9750,7 +9830,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.0" + "source": "https://github.com/symfony/process/tree/v7.4.4" }, "funding": [ { @@ -9761,45 +9841,49 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-17T09:11:12+00:00" + "time": "2026-01-20T09:23:51+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.3.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "reference": "d6edf266746dd0b8e81e754a79da77b08dc00531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d6edf266746dd0b8e81e754a79da77b08dc00531", + "reference": "d6edf266746dd0b8e81e754a79da77b08dc00531", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^7.4|^8.0" }, "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" + "php-http/discovery": "<1.15" }, "require-dev": { "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/browser-kit": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0" }, "type": "symfony-bridge", "autoload": { @@ -9833,7 +9917,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v8.0.4" }, "funding": [ { @@ -9844,25 +9928,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-26T08:57:56+00:00" + "time": "2026-01-03T23:40:55+00:00" }, { "name": "symfony/routing", - "version": "v7.3.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8e213820c5fea844ecea29203d2a308019007c15" + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", - "reference": "8e213820c5fea844ecea29203d2a308019007c15", + "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", + "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", "shasum": "" }, "require": { @@ -9876,11 +9964,11 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9914,7 +10002,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.0" + "source": "https://github.com/symfony/routing/tree/v7.4.4" }, "funding": [ { @@ -9925,25 +10013,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-05-24T20:43:28+00:00" + "time": "2026-01-12T12:19:02+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -9997,7 +10089,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -10008,44 +10100,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v7.3.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + "reference": "758b372d6882506821ed666032e43020c4f57194" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", + "reference": "758b372d6882506821ed666032e43020c4f57194", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -10084,7 +10179,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.0" + "source": "https://github.com/symfony/string/tree/v8.0.4" }, "funding": [ { @@ -10095,43 +10190,40 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-20T20:19:01+00:00" + "time": "2026-01-12T12:37:40+00:00" }, { "name": "symfony/translation", - "version": "v7.3.1", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "241d5ac4910d256660238a7ecf250deba4c73063" + "reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/241d5ac4910d256660238a7ecf250deba4c73063", - "reference": "241d5ac4910d256660238a7ecf250deba4c73063", + "url": "https://api.github.com/repos/symfony/translation/zipball/db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", + "reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation-contracts": "^3.6.1" }, "conflict": { "nikic/php-parser": "<5.0", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" + "symfony/service-contracts": "<2.5" }, "provide": { "symfony/translation-implementation": "2.3|3.0" @@ -10139,17 +10231,17 @@ "require-dev": { "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -10180,7 +10272,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.3.1" + "source": "https://github.com/symfony/translation/tree/v8.0.4" }, "funding": [ { @@ -10191,25 +10283,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2026-01-13T13:06:50+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + "reference": "65a8bc82080447fae78373aa10f8d13b38338977" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", + "reference": "65a8bc82080447fae78373aa10f8d13b38338977", "shasum": "" }, "require": { @@ -10258,7 +10354,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" }, "funding": [ { @@ -10269,25 +10365,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-27T08:32:26+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/uid", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", "shasum": "" }, "require": { @@ -10295,7 +10395,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -10332,7 +10432,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.3.1" + "source": "https://github.com/symfony/uid/tree/v7.4.4" }, "funding": [ { @@ -10343,25 +10443,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2026-01-03T23:30:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.3.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42" + "reference": "0e4769b46a0c3c62390d124635ce59f66874b282" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", - "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e4769b46a0c3c62390d124635ce59f66874b282", + "reference": "0e4769b46a0c3c62390d124635ce59f66874b282", "shasum": "" }, "require": { @@ -10373,11 +10477,10 @@ "symfony/console": "<6.4" }, "require-dev": { - "ext-iconv": "*", - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -10416,7 +10519,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.1" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.4" }, "funding": [ { @@ -10427,32 +10530,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2026-01-01T22:13:48+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", - "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41", + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "php": "^7.4 || ^8.0", - "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^2.0", @@ -10485,9 +10592,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0" }, - "time": "2024-12-21T16:25:41+00:00" + "time": "2025-12-02T11:56:42+00:00" }, { "name": "tpetry/laravel-query-expressions", @@ -10556,16 +10663,16 @@ }, { "name": "typesense/typesense-php", - "version": "v5.1.0", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/typesense/typesense-php.git", - "reference": "0e8dee542c05b201becf4734319075e6c4d540b3" + "reference": "1fbf79e1c10a8fd4cc3df9c3cddbe158e93542f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/typesense/typesense-php/zipball/0e8dee542c05b201becf4734319075e6c4d540b3", - "reference": "0e8dee542c05b201becf4734319075e6c4d540b3", + "url": "https://api.github.com/repos/typesense/typesense-php/zipball/1fbf79e1c10a8fd4cc3df9c3cddbe158e93542f7", + "reference": "1fbf79e1c10a8fd4cc3df9c3cddbe158e93542f7", "shasum": "" }, "require": { @@ -10623,30 +10730,99 @@ "type": "github" } ], - "time": "2025-05-05T17:35:26+00:00" + "time": "2025-08-15T15:21:26+00:00" + }, + { + "name": "ueberdosis/tiptap-php", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/ueberdosis/tiptap-php.git", + "reference": "6ea321fa665080e1a72ac5f52dfab19f6a292e2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ueberdosis/tiptap-php/zipball/6ea321fa665080e1a72ac5f52dfab19f6a292e2d", + "reference": "6ea321fa665080e1a72ac5f52dfab19f6a292e2d", + "shasum": "" + }, + "require": { + "php": "^8.0", + "scrivo/highlight.php": "^9.18", + "spatie/shiki-php": "^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.5", + "pestphp/pest": "^1.21", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Tiptap\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Hans Pagel", + "email": "humans@tiptap.dev", + "role": "Developer" + } + ], + "description": "A PHP package to work with Tiptap output", + "homepage": "https://github.com/ueberdosis/tiptap-php", + "keywords": [ + "prosemirror", + "tiptap", + "ueberdosis" + ], + "support": { + "issues": "https://github.com/ueberdosis/tiptap-php/issues", + "source": "https://github.com/ueberdosis/tiptap-php/tree/2.1.0" + }, + "funding": [ + { + "url": "https://tiptap.dev/pricing", + "type": "custom" + }, + { + "url": "https://github.com/ueberdosis", + "type": "github" + }, + { + "url": "https://opencollective.com/tiptap", + "type": "open_collective" + } + ], + "time": "2026-01-10T16:40:02+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.2", + "version": "v5.6.3", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + "reference": "955e7815d677a3eaa7075231212f2110983adecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", - "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.3", + "graham-campbell/result-type": "^1.1.4", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3", - "symfony/polyfill-ctype": "^1.24", - "symfony/polyfill-mbstring": "^1.24", - "symfony/polyfill-php80": "^1.24" + "phpoption/phpoption": "^1.9.5", + "symfony/polyfill-ctype": "^1.26", + "symfony/polyfill-mbstring": "^1.26", + "symfony/polyfill-php80": "^1.26" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -10695,7 +10871,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" }, "funding": [ { @@ -10707,7 +10883,7 @@ "type": "tidelift" } ], - "time": "2025-04-30T23:37:27+00:00" + "time": "2025-12-27T19:49:13+00:00" }, { "name": "voku/portable-ascii", @@ -10781,89 +10957,31 @@ "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2024-11-21T01:49:47+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.16.0", + "version": "v3.16.5", "source": { "type": "git", - "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "f265cf5e38577d42311f1a90d619bcd3740bea23" + "url": "https://github.com/fruitcake/laravel-debugbar.git", + "reference": "e85c0a8464da67e5b4a53a42796d46a43fc06c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f265cf5e38577d42311f1a90d619bcd3740bea23", - "reference": "f265cf5e38577d42311f1a90d619bcd3740bea23", + "url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/e85c0a8464da67e5b4a53a42796d46a43fc06c9a", + "reference": "e85c0a8464da67e5b4a53a42796d46a43fc06c9a", "shasum": "" }, "require": { - "illuminate/routing": "^9|^10|^11|^12", - "illuminate/session": "^9|^10|^11|^12", - "illuminate/support": "^9|^10|^11|^12", + "illuminate/routing": "^10|^11|^12", + "illuminate/session": "^10|^11|^12", + "illuminate/support": "^10|^11|^12", "php": "^8.1", - "php-debugbar/php-debugbar": "~2.2.0", - "symfony/finder": "^6|^7" + "php-debugbar/php-debugbar": "^2.2.4", + "symfony/finder": "^6|^7|^8" }, "require-dev": { "mockery/mockery": "^1.3.3", @@ -10913,8 +11031,8 @@ "webprofiler" ], "support": { - "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.0" + "issues": "https://github.com/fruitcake/laravel-debugbar/issues", + "source": "https://github.com/fruitcake/laravel-debugbar/tree/v3.16.5" }, "funding": [ { @@ -10926,20 +11044,20 @@ "type": "github" } ], - "time": "2025-07-14T11:56:43+00:00" + "time": "2026-01-23T15:03:22+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "8d00250cba25728373e92c1d8dcebcbf64623d29" + "reference": "b106f7ee85f263c4f103eca49e7bf3862c2e5e75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d00250cba25728373e92c1d8dcebcbf64623d29", - "reference": "8d00250cba25728373e92c1d8dcebcbf64623d29", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/b106f7ee85f263c4f103eca49e7bf3862c2e5e75", + "reference": "b106f7ee85f263c4f103eca49e7bf3862c2e5e75", "shasum": "" }, "require": { @@ -11008,7 +11126,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.6.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.6.1" }, "funding": [ { @@ -11020,7 +11138,7 @@ "type": "github" } ], - "time": "2025-07-17T20:11:57+00:00" + "time": "2025-12-10T09:11:07+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -11076,16 +11194,16 @@ }, { "name": "brianium/paratest", - "version": "v7.8.3", + "version": "v7.8.4", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "a585c346ddf1bec22e51e20b5387607905604a71" + "reference": "130a9bf0e269ee5f5b320108f794ad03e275cad4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/a585c346ddf1bec22e51e20b5387607905604a71", - "reference": "a585c346ddf1bec22e51e20b5387607905604a71", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/130a9bf0e269ee5f5b320108f794ad03e275cad4", + "reference": "130a9bf0e269ee5f5b320108f794ad03e275cad4", "shasum": "" }, "require": { @@ -11094,26 +11212,26 @@ "ext-reflection": "*", "ext-simplexml": "*", "fidry/cpu-core-counter": "^1.2.0", - "jean85/pretty-package-versions": "^2.1.0", + "jean85/pretty-package-versions": "^2.1.1", "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "phpunit/php-code-coverage": "^11.0.9 || ^12.0.4", - "phpunit/php-file-iterator": "^5.1.0 || ^6", - "phpunit/php-timer": "^7.0.1 || ^8", - "phpunit/phpunit": "^11.5.11 || ^12.0.6", - "sebastian/environment": "^7.2.0 || ^8", - "symfony/console": "^6.4.17 || ^7.2.1", - "symfony/process": "^6.4.19 || ^7.2.4" + "phpunit/php-code-coverage": "^11.0.10", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-timer": "^7.0.1", + "phpunit/phpunit": "^11.5.24", + "sebastian/environment": "^7.2.1", + "symfony/console": "^6.4.22 || ^7.3.0", + "symfony/process": "^6.4.20 || ^7.3.0" }, "require-dev": { "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^2.1.6", - "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpstan/phpstan-phpunit": "^2.0.4", - "phpstan/phpstan-strict-rules": "^2.0.3", - "squizlabs/php_codesniffer": "^3.11.3", - "symfony/filesystem": "^6.4.13 || ^7.2.0" + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.6", + "phpstan/phpstan-strict-rules": "^2.0.4", + "squizlabs/php_codesniffer": "^3.13.2", + "symfony/filesystem": "^6.4.13 || ^7.3.0" }, "bin": [ "bin/paratest", @@ -11153,7 +11271,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.8.3" + "source": "https://github.com/paratestphp/paratest/tree/v7.8.4" }, "funding": [ { @@ -11165,7 +11283,7 @@ "type": "paypal" } ], - "time": "2025-03-05T08:29:11+00:00" + "time": "2025-06-23T06:07:21+00:00" }, { "name": "clue/ndjson-react", @@ -11233,22 +11351,22 @@ }, { "name": "composer/class-map-generator", - "version": "1.6.1", + "version": "1.7.1", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34" + "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/134b705ddb0025d397d8318a75825fe3c9d1da34", - "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8f5fa3cc214230e71f54924bd0197a3bcc705eb1", + "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1", "shasum": "" }, "require": { "composer/pcre": "^2.1 || ^3.1", "php": "^7.2 || ^8.0", - "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8" }, "require-dev": { "phpstan/phpstan": "^1.12 || ^2", @@ -11256,7 +11374,7 @@ "phpstan/phpstan-phpunit": "^1 || ^2", "phpstan/phpstan-strict-rules": "^1.1 || ^2", "phpunit/phpunit": "^8", - "symfony/filesystem": "^5.4 || ^6" + "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8" }, "type": "library", "extra": { @@ -11286,7 +11404,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.6.1" + "source": "https://github.com/composer/class-map-generator/tree/1.7.1" }, "funding": [ { @@ -11296,13 +11414,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2025-03-24T13:50:44+00:00" + "time": "2025-12-29T13:15:25+00:00" }, { "name": "composer/xdebug-handler", @@ -11370,6 +11484,54 @@ ], "time": "2024-05-06T16:37:16+00:00" }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, { "name": "evenement/evenement", "version": "v3.0.2", @@ -11482,16 +11644,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { @@ -11501,10 +11663,10 @@ "fidry/makefile": "^0.2.0", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, @@ -11531,7 +11693,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" }, "funding": [ { @@ -11539,20 +11701,67 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2025-08-14T07:29:31+00:00" + }, + { + "name": "filament/upgrade", + "version": "v4.6.0", + "source": { + "type": "git", + "url": "https://github.com/filamentphp/upgrade.git", + "reference": "31b03a80a99e203ba0b7bfbfb9566974e0346be7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filamentphp/upgrade/zipball/31b03a80a99e203ba0b7bfbfb9566974e0346be7", + "reference": "31b03a80a99e203ba0b7bfbfb9566974e0346be7", + "shasum": "" + }, + "require": { + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "rector/rector": "^2.0" + }, + "bin": [ + "bin/filament-v4" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Filament\\Upgrade\\UpgradeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Filament\\Upgrade\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Upgrade Filament v3 code to Filament v4.", + "homepage": "https://github.com/filamentphp/filament", + "support": { + "issues": "https://github.com/filamentphp/filament/issues", + "source": "https://github.com/filamentphp/filament" + }, + "time": "2025-11-28T11:21:29+00:00" }, { "name": "filp/whoops", - "version": "2.18.3", + "version": "2.18.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "59a123a3d459c5a23055802237cb317f609867e5" + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5", - "reference": "59a123a3d459c5a23055802237cb317f609867e5", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", "shasum": "" }, "require": { @@ -11602,7 +11811,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.18.3" + "source": "https://github.com/filp/whoops/tree/2.18.4" }, "funding": [ { @@ -11610,63 +11819,62 @@ "type": "github" } ], - "time": "2025-06-16T00:02:10+00:00" + "time": "2025-08-08T12:00:00+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.84.0", + "version": "v3.93.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "38dad0767bf2a9b516b976852200ae722fe984ca" + "reference": "50895a07cface1385082e4caa6a6786c4e033468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/38dad0767bf2a9b516b976852200ae722fe984ca", - "reference": "38dad0767bf2a9b516b976852200ae722fe984ca", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/50895a07cface1385082e4caa6a6786c4e033468", + "reference": "50895a07cface1385082e4caa6a6786c4e033468", "shasum": "" }, "require": { - "clue/ndjson-react": "^1.0", + "clue/ndjson-react": "^1.3", "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.5", "ext-filter": "*", "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", "react/child-process": "^0.6.6", - "react/event-loop": "^1.0", - "react/promise": "^2.11 || ^3.0", - "react/socket": "^1.0", - "react/stream": "^1.0", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", - "symfony/console": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0", - "symfony/polyfill-mbstring": "^1.32", - "symfony/polyfill-php80": "^1.32", - "symfony/polyfill-php81": "^1.32", - "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.6", - "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.4", - "keradus/cli-executor": "^2.2", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.7", + "infection/infection": "^0.32", + "justinrainbow/json-schema": "^6.6", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.8", - "php-cs-fixer/accessible-object": "^1.1", + "php-coveralls/php-coveralls": "^2.9", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25", - "symfony/polyfill-php84": "^1.32", - "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1", - "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1" + "phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.48", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -11681,7 +11889,7 @@ "PhpCsFixer\\": "src/" }, "exclude-from-classmap": [ - "src/Fixer/Internal/*" + "src/**/Internal/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -11707,7 +11915,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.84.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.93.0" }, "funding": [ { @@ -11715,7 +11923,7 @@ "type": "github" } ], - "time": "2025-07-15T18:21:57+00:00" + "time": "2026-01-23T17:33:21+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -11768,18 +11976,157 @@ }, "time": "2025-04-30T06:54:44+00:00" }, + { + "name": "laravel/boost", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/boost.git", + "reference": "4bbcc99c4b05fab18a848e65c8af9ad4173360dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/boost/zipball/4bbcc99c4b05fab18a848e65c8af9ad4173360dd", + "reference": "4bbcc99c4b05fab18a848e65c8af9ad4173360dd", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^7.9", + "illuminate/console": "^11.45.3|^12.41.1", + "illuminate/contracts": "^11.45.3|^12.41.1", + "illuminate/routing": "^11.45.3|^12.41.1", + "illuminate/support": "^11.45.3|^12.41.1", + "laravel/mcp": "^0.5.1", + "laravel/prompts": "^0.3.10", + "laravel/roster": "^0.2.9", + "php": "^8.2" + }, + "require-dev": { + "laravel/pint": "^1.27.0", + "mockery/mockery": "^1.6.12", + "orchestra/testbench": "^9.15.0|^10.6", + "pestphp/pest": "^2.36.0|^3.8.4|^4.1.5", + "phpstan/phpstan": "^2.1.27", + "rector/rector": "^2.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Boost\\BoostServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Boost\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.", + "homepage": "https://github.com/laravel/boost", + "keywords": [ + "ai", + "dev", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/boost/issues", + "source": "https://github.com/laravel/boost" + }, + "time": "2026-01-27T11:20:21+00:00" + }, + { + "name": "laravel/mcp", + "version": "v0.5.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/mcp.git", + "reference": "b9bdd8d6f8b547c8733fe6826b1819341597ba3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/mcp/zipball/b9bdd8d6f8b547c8733fe6826b1819341597ba3c", + "reference": "b9bdd8d6f8b547c8733fe6826b1819341597ba3c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/container": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/http": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/json-schema": "^12.41.1", + "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/validation": "^10.49.0|^11.45.3|^12.41.1", + "php": "^8.1" + }, + "require-dev": { + "laravel/pint": "^1.20", + "orchestra/testbench": "^8.36|^9.15|^10.8", + "pestphp/pest": "^2.36.0|^3.8.4|^4.1.0", + "phpstan/phpstan": "^2.1.27", + "rector/rector": "^2.2.4" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" + }, + "providers": [ + "Laravel\\Mcp\\Server\\McpServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Mcp\\": "src/", + "Laravel\\Mcp\\Server\\": "src/Server/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Rapidly build MCP servers for your Laravel applications.", + "homepage": "https://github.com/laravel/mcp", + "keywords": [ + "laravel", + "mcp" + ], + "support": { + "issues": "https://github.com/laravel/mcp/issues", + "source": "https://github.com/laravel/mcp" + }, + "time": "2025-12-19T19:32:34+00:00" + }, { "name": "laravel/pint", - "version": "v1.24.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" + "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "url": "https://api.github.com/repos/laravel/pint/zipball/c67b4195b75491e4dfc6b00b1c78b68d86f54c90", + "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90", "shasum": "" }, "require": { @@ -11790,22 +12137,19 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.82.2", - "illuminate/view": "^11.45.1", - "larastan/larastan": "^3.5.0", - "laravel-zero/framework": "^11.45.0", + "friendsofphp/php-cs-fixer": "^3.92.4", + "illuminate/view": "^12.44.0", + "larastan/larastan": "^3.8.1", + "laravel-zero/framework": "^12.0.4", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.1", - "pestphp/pest": "^2.36.0" + "nunomaduro/termwind": "^2.3.3", + "pestphp/pest": "^3.8.4" }, "bin": [ "builds/pint" ], "type": "project", "autoload": { - "files": [ - "overrides/Runner/Parallel/ProcessFactory.php" - ], "psr-4": { "App\\": "app/", "Database\\Seeders\\": "database/seeders/", @@ -11825,6 +12169,7 @@ "description": "An opinionated code formatter for PHP.", "homepage": "https://laravel.com", "keywords": [ + "dev", "format", "formatter", "lint", @@ -11835,20 +12180,81 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-07-10T18:09:32+00:00" + "time": "2026-01-05T16:49:17+00:00" + }, + { + "name": "laravel/roster", + "version": "v0.2.9", + "source": { + "type": "git", + "url": "https://github.com/laravel/roster.git", + "reference": "82bbd0e2de614906811aebdf16b4305956816fa6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6", + "reference": "82bbd0e2de614906811aebdf16b4305956816fa6", + "shasum": "" + }, + "require": { + "illuminate/console": "^10.0|^11.0|^12.0", + "illuminate/contracts": "^10.0|^11.0|^12.0", + "illuminate/routing": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "php": "^8.1|^8.2", + "symfony/yaml": "^6.4|^7.2" + }, + "require-dev": { + "laravel/pint": "^1.14", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^8.22.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "phpstan/phpstan": "^2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Roster\\RosterServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Roster\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Detect packages & approaches in use within a Laravel project", + "homepage": "https://github.com/laravel/roster", + "keywords": [ + "dev", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/roster/issues", + "source": "https://github.com/laravel/roster" + }, + "time": "2025-10-20T09:56:46+00:00" }, { "name": "laravel/sail", - "version": "v1.44.0", + "version": "v1.52.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe" + "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe", - "reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe", + "url": "https://api.github.com/repos/laravel/sail/zipball/64ac7d8abb2dbcf2b76e61289451bae79066b0b3", + "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3", "shasum": "" }, "require": { @@ -11861,7 +12267,7 @@ }, "require-dev": { "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^1.10" + "phpstan/phpstan": "^2.0" }, "bin": [ "bin/sail" @@ -11898,7 +12304,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2025-07-04T16:17:06+00:00" + "time": "2026-01-01T02:46:03+00:00" }, { "name": "mockery/mockery", @@ -11985,16 +12391,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.3", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -12033,7 +12439,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -12041,20 +12447,20 @@ "type": "tidelift" } ], - "time": "2025-07-05T12:25:42+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.8.2", + "version": "v8.8.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", "shasum": "" }, "require": { @@ -12076,7 +12482,7 @@ "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2", + "pestphp/pest": "^3.8.2 || ^4.0.0", "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", @@ -12140,42 +12546,42 @@ "type": "patreon" } ], - "time": "2025-06-25T02:12:12+00:00" + "time": "2025-11-20T02:55:25+00:00" }, { "name": "pestphp/pest", - "version": "v3.8.2", + "version": "v3.8.4", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d" + "reference": "72cf695554420e21858cda831d5db193db102574" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/c6244a8712968dbac88eb998e7ff3b5caa556b0d", - "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d", + "url": "https://api.github.com/repos/pestphp/pest/zipball/72cf695554420e21858cda831d5db193db102574", + "reference": "72cf695554420e21858cda831d5db193db102574", "shasum": "" }, "require": { - "brianium/paratest": "^7.8.3", - "nunomaduro/collision": "^8.8.0", - "nunomaduro/termwind": "^2.3.0", + "brianium/paratest": "^7.8.4", + "nunomaduro/collision": "^8.8.2", + "nunomaduro/termwind": "^2.3.1", "pestphp/pest-plugin": "^3.0.0", - "pestphp/pest-plugin-arch": "^3.1.0", + "pestphp/pest-plugin-arch": "^3.1.1", "pestphp/pest-plugin-mutate": "^3.0.5", "php": "^8.2.0", - "phpunit/phpunit": "^11.5.15" + "phpunit/phpunit": "^11.5.33" }, "conflict": { "filp/whoops": "<2.16.0", - "phpunit/phpunit": ">11.5.15", + "phpunit/phpunit": ">11.5.33", "sebastian/exporter": "<6.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^3.4.0", - "pestphp/pest-plugin-type-coverage": "^3.5.0", - "symfony/process": "^7.2.5" + "pestphp/pest-plugin-type-coverage": "^3.6.1", + "symfony/process": "^7.3.0" }, "bin": [ "bin/pest" @@ -12240,7 +12646,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v3.8.2" + "source": "https://github.com/pestphp/pest/tree/v3.8.4" }, "funding": [ { @@ -12252,7 +12658,7 @@ "type": "github" } ], - "time": "2025-04-17T10:53:02+00:00" + "time": "2025-08-20T19:12:42+00:00" }, { "name": "pestphp/pest-plugin", @@ -12791,31 +13197,32 @@ }, { "name": "php-debugbar/php-debugbar", - "version": "v2.2.4", + "version": "v2.2.6", "source": { "type": "git", "url": "https://github.com/php-debugbar/php-debugbar.git", - "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35" + "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3146d04671f51f69ffec2a4207ac3bdcf13a9f35", - "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/abb9fa3c5c8dbe7efe03ddba56782917481de3e8", + "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8", "shasum": "" }, "require": { - "php": "^8", + "php": "^8.1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4|^5|^6|^7" + "symfony/var-dumper": "^5.4|^6.4|^7.3|^8.0" }, "replace": { "maximebf/debugbar": "self.version" }, "require-dev": { "dbrekelmans/bdi": "^1", - "phpunit/phpunit": "^8|^9", + "phpunit/phpunit": "^10", + "symfony/browser-kit": "^6.0|7.0", "symfony/panther": "^1|^2.1", - "twig/twig": "^1.38|^2.7|^3.0" + "twig/twig": "^3.11.2" }, "suggest": { "kriswallsmith/assetic": "The best way to manage assets", @@ -12825,7 +13232,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } }, "autoload": { @@ -12858,9 +13265,9 @@ ], "support": { "issues": "https://github.com/php-debugbar/php-debugbar/issues", - "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.4" + "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.6" }, - "time": "2025-07-22T14:01:30+00:00" + "time": "2025-12-22T13:21:32+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -12917,16 +13324,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.2", + "version": "5.6.6", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", "shasum": "" }, "require": { @@ -12936,7 +13343,7 @@ "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" + "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { "mockery/mockery": "~1.3.5 || ~1.6.0", @@ -12975,22 +13382,22 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" }, - "time": "2025-04-13T19:20:35+00:00" + "time": "2025-12-22T21:13:58+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.10.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", "shasum": "" }, "require": { @@ -13033,22 +13440,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" }, - "time": "2024-11-09T15:12:26+00:00" + "time": "2025-11-21T15:09:14+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.2.0", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { @@ -13067,54 +13474,107 @@ }, "type": "library", "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" + }, + "time": "2026-01-25T14:56:51+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.37", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/28cd424c5ea984128c95cfa7ea658808e8954e49", + "reference": "28cd424c5ea984128c95cfa7ea658808e8954e49", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, - "time": "2025-07-13T07:04:09+00:00" + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-01-24T08:21:55+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "11.0.10", + "version": "11.0.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", - "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.4.0", + "nikic/php-parser": "^5.7.0", "php": ">=8.2", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-text-template": "^4.0.1", "sebastian/code-unit-reverse-lookup": "^4.0.1", "sebastian/complexity": "^4.0.1", - "sebastian/environment": "^7.2.0", + "sebastian/environment": "^7.2.1", "sebastian/lines-of-code": "^3.0.1", "sebastian/version": "^5.0.2", - "theseer/tokenizer": "^1.2.3" + "theseer/tokenizer": "^1.3.1" }, "require-dev": { - "phpunit/phpunit": "^11.5.2" + "phpunit/phpunit": "^11.5.46" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -13152,7 +13612,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" }, "funding": [ { @@ -13172,7 +13632,7 @@ "type": "tidelift" } ], - "time": "2025-06-18T08:56:18+00:00" + "time": "2025-12-24T07:01:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -13421,16 +13881,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.15", + "version": "11.5.33", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c" + "reference": "5965e9ff57546cb9137c0ff6aa78cb7442b05cf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", - "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5965e9ff57546cb9137c0ff6aa78cb7442b05cf6", + "reference": "5965e9ff57546cb9137c0ff6aa78cb7442b05cf6", "shasum": "" }, "require": { @@ -13440,24 +13900,24 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.0", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.9", + "phpunit/php-code-coverage": "^11.0.10", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.3", - "sebastian/comparator": "^6.3.1", + "sebastian/comparator": "^6.3.2", "sebastian/diff": "^6.0.2", - "sebastian/environment": "^7.2.0", + "sebastian/environment": "^7.2.1", "sebastian/exporter": "^6.3.0", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", - "sebastian/type": "^5.1.2", + "sebastian/type": "^5.1.3", "sebastian/version": "^5.0.2", "staabm/side-effects-detector": "^1.0.5" }, @@ -13502,7 +13962,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.33" }, "funding": [ { @@ -13513,12 +13973,20 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2025-03-23T16:02:11+00:00" + "time": "2025-08-16T05:19:02+00:00" }, { "name": "react/cache", @@ -13594,16 +14062,16 @@ }, { "name": "react/child-process", - "version": "v0.6.6", + "version": "v0.6.7", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { @@ -13657,7 +14125,7 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, "funding": [ { @@ -13665,20 +14133,20 @@ "type": "open_collective" } ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2025-12-23T15:25:20+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -13733,7 +14201,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -13741,20 +14209,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -13805,7 +14273,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -13813,27 +14281,27 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", - "version": "v3.2.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpstan/phpstan": "1.12.28 || 1.4.10", "phpunit/phpunit": "^9.6 || ^7.5" }, "type": "library", @@ -13878,7 +14346,7 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v3.3.0" }, "funding": [ { @@ -13886,20 +14354,20 @@ "type": "open_collective" } ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2025-08-19T18:57:03+00:00" }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -13958,7 +14426,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -13966,7 +14434,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -14046,6 +14514,66 @@ ], "time": "2024-06-11T12:45:25+00:00" }, + { + "name": "rector/rector", + "version": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9227d7a24b0f23ae941057509364f948d5da9ab2", + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.36" + }, + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "suggest": { + "ext-dom": "To manipulate phpunit.xml via the custom-rule command" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "homepage": "https://getrector.com/", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" + ], + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/2.3.4" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2026-01-21T14:49:03+00:00" + }, { "name": "sebastian/cli-parser", "version": "3.0.2", @@ -14218,16 +14746,16 @@ }, { "name": "sebastian/comparator", - "version": "6.3.1", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", - "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", "shasum": "" }, "require": { @@ -14286,15 +14814,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2025-03-07T06:57:01+00:00" + "time": "2026-01-24T09:26:40+00:00" }, { "name": "sebastian/complexity", @@ -14499,16 +15039,16 @@ }, { "name": "sebastian/exporter", - "version": "6.3.0", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", - "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", "shasum": "" }, "require": { @@ -14522,7 +15062,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -14565,15 +15105,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-12-05T09:17:50+00:00" + "time": "2025-09-24T06:12:51+00:00" }, { "name": "sebastian/global-state", @@ -14811,23 +15363,23 @@ }, { "name": "sebastian/recursion-context", - "version": "6.0.2", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -14863,28 +15415,40 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2024-07-03T05:10:34+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { "name": "sebastian/type", - "version": "5.1.2", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", - "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { @@ -14920,15 +15484,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2025-03-18T13:35:50+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { "name": "sebastian/version", @@ -14986,16 +15562,16 @@ }, { "name": "spatie/backtrace", - "version": "1.7.4", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe" + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/cd37a49fce7137359ac30ecc44ef3e16404cccbe", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8c0f16a59ae35ec8c62d85c3c17585158f430110", + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110", "shasum": "" }, "require": { @@ -15033,7 +15609,8 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.7.4" + "issues": "https://github.com/spatie/backtrace/issues", + "source": "https://github.com/spatie/backtrace/tree/1.8.1" }, "funding": [ { @@ -15045,7 +15622,7 @@ "type": "other" } ], - "time": "2025-05-08T15:41:09+00:00" + "time": "2025-08-26T08:22:30+00:00" }, { "name": "spatie/error-solutions", @@ -15275,38 +15852,39 @@ }, { "name": "spatie/laravel-ignition", - "version": "2.9.1", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "1baee07216d6748ebd3a65ba97381b051838707a" + "reference": "2abefdcca6074a9155f90b4ccb3345af8889d5f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a", - "reference": "1baee07216d6748ebd3a65ba97381b051838707a", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2abefdcca6074a9155f90b4ccb3345af8889d5f5", + "reference": "2abefdcca6074a9155f90b4ccb3345af8889d5f5", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1", - "spatie/ignition": "^1.15", - "symfony/console": "^6.2.3|^7.0", - "symfony/var-dumper": "^6.2.3|^7.0" + "illuminate/support": "^11.0|^12.0", + "nesbot/carbon": "^2.72|^3.0", + "php": "^8.2", + "spatie/ignition": "^1.15.1", + "symfony/console": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "require-dev": { - "livewire/livewire": "^2.11|^3.3.5", - "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1|^0.10", - "orchestra/testbench": "8.22.3|^9.0|^10.0", - "pestphp/pest": "^2.34|^3.7", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0", - "phpstan/phpstan-phpunit": "^1.3.16|^2.0", - "vlucas/phpdotenv": "^5.5" + "livewire/livewire": "^3.7.0|^4.0", + "mockery/mockery": "^1.6.12", + "openai-php/client": "^0.10.3", + "orchestra/testbench": "^v9.16.0|^10.6", + "pestphp/pest": "^3.7|^4.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.8", + "vlucas/phpdotenv": "^5.6.2" }, "suggest": { "openai-php/client": "Require get solutions from OpenAI", @@ -15362,7 +15940,7 @@ "type": "github" } ], - "time": "2025-02-20T13:13:55+00:00" + "time": "2026-01-20T13:16:11+00:00" }, { "name": "staabm/side-effects-detector", @@ -15416,75 +15994,9 @@ ], "time": "2024-10-20T05:08:20+00:00" }, - { - "name": "symfony/filesystem", - "version": "v7.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-25T15:15:23+00:00" - }, { "name": "symfony/polyfill-php81", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -15540,7 +16052,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -15551,6 +16063,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -15560,20 +16076,20 @@ }, { "name": "symfony/stopwatch", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -15602,7 +16118,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" + "source": "https://github.com/symfony/stopwatch/tree/v8.0.0" }, "funding": [ { @@ -15613,37 +16129,41 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-02-24T10:49:57+00:00" + "time": "2025-08-04T07:36:47+00:00" }, { "name": "symfony/yaml", - "version": "v7.3.1", + "version": "v7.4.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb" + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0c3555045a46ab3cd4cc5a69d161225195230edb", - "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb", + "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -15674,7 +16194,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.3.1" + "source": "https://github.com/symfony/yaml/tree/v7.4.1" }, "funding": [ { @@ -15685,12 +16205,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-03T06:57:57+00:00" + "time": "2025-12-04T18:11:45+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", @@ -15753,16 +16277,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -15791,7 +16315,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -15799,7 +16323,69 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" + }, + { + "name": "webmozart/assert", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", + "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-feature/2-0": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/2.1.2" + }, + "time": "2026-01-13T14:02:24+00:00" } ], "aliases": [], @@ -15808,8 +16394,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.2" + "php": "^8.4" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/opencode.json b/opencode.json new file mode 100644 index 00000000..53e16f3d --- /dev/null +++ b/opencode.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "laravel-boost": { + "type": "local", + "enabled": true, + "command": [ + "php", + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 90f38f24..f5160339 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,12 +6,15 @@ "": { "devDependencies": { "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/postcss": "^4.1.18", "@tailwindcss/typography": "^0.5.16", + "@tailwindcss/vite": "^4.1.18", "autoprefixer": "^10.4.20", "axios": "^1.7.9", "laravel-vite-plugin": "^1.2.0", "postcss": "^8.5.1", - "tailwindcss": "^3.4.4", + "postcss-import": "^16.1.1", + "tailwindcss": "^4.1.18", "vite": "^6.0.11" } }, @@ -453,88 +456,55 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, - "engines": { - "node": ">=6.0.0" + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.34.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz", @@ -814,6 +784,276 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" } }, + "node_modules/@tailwindcss/node": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.0", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "postcss": "^8.4.41", + "tailwindcss": "4.1.18" + } + }, "node_modules/@tailwindcss/typography": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", @@ -830,6 +1070,21 @@ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -837,31 +1092,6 @@ "dev": true, "license": "MIT" }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -918,43 +1148,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browserslist": { "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", @@ -988,15 +1181,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001697", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz", @@ -1018,45 +1202,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1069,21 +1214,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1105,17 +1235,15 @@ "node": ">=0.4.0" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } }, "node_modules/electron-to-chromium": { "version": "1.5.91", @@ -1124,6 +1252,20 @@ "dev": true, "license": "ISC" }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/esbuild": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", @@ -1175,55 +1317,6 @@ "node": ">=6" } }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -1271,12 +1364,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1300,37 +1387,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } + "license": "ISC" }, "node_modules/hasown": { "version": "2.0.0", @@ -1344,119 +1406,308 @@ "node": ">= 0.4" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/laravel-vite-plugin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", + "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "picocolors": "^1.0.0", + "vite-plugin-full-reload": "^1.1.0" + }, + "bin": { + "clean-orphaned-assets": "bin/clean.js" }, "engines": { - "node": ">=8" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0" } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "hasown": "^2.0.0" + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "jiti": "bin/jiti.js" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/laravel-vite-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", - "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "picocolors": "^1.0.0", - "vite-plugin-full-reload": "^1.1.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, - "bin": { - "clean-orphaned-assets": "bin/clean.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": ">= 12.0.0" }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, "node_modules/lodash.castarray": { "version": "4.4.0", @@ -1476,27 +1727,14 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/mime-db": { @@ -1529,29 +1767,6 @@ "mini-svg-data-uri": "cli.js" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", @@ -1578,15 +1793,6 @@ "dev": true, "license": "MIT" }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", @@ -1596,42 +1802,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -1666,15 +1836,6 @@ "node": ">=0.10.0" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/postcss": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", @@ -1705,9 +1866,9 @@ } }, "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.1.tgz", + "integrity": "sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==", "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", @@ -1715,92 +1876,12 @@ "resolve": "^1.1.7" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" }, "peerDependencies": { "postcss": "^8.0.0" } }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-nested/node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-selector-parser": { "version": "6.0.10", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", @@ -1826,26 +1907,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -1855,18 +1916,6 @@ "pify": "^2.3.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -1884,16 +1933,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, "node_modules/rollup": { "version": "4.34.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.2.tgz", @@ -1933,29 +1972,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1966,28 +1982,6 @@ "node": ">=0.10.0" } }, - "node_modules/sucrase": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", - "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -2001,94 +1995,26 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", - "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", - "dev": true, - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } + "license": "MIT" }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, + "license": "MIT", "engines": { - "node": ">=0.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" + "node": ">=6" }, - "engines": { - "node": ">=8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, "node_modules/update-browserslist-db": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", @@ -2207,25 +2133,6 @@ "picocolors": "^1.0.0", "picomatch": "^2.3.1" } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } } } } diff --git a/package.json b/package.json index 295e0e5b..8c646b16 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,15 @@ }, "devDependencies": { "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/postcss": "^4.1.18", "@tailwindcss/typography": "^0.5.16", + "@tailwindcss/vite": "^4.1.18", "autoprefixer": "^10.4.20", "axios": "^1.7.9", "laravel-vite-plugin": "^1.2.0", "postcss": "^8.5.1", - "tailwindcss": "^3.4.4", + "postcss-import": "^16.1.1", + "tailwindcss": "^4.1.18", "vite": "^6.0.11" } } diff --git a/postcss.config.js b/postcss.config.js index d41ad635..3300dedf 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,7 @@ export default { plugins: { - tailwindcss: {}, + 'postcss-import': {}, + '@tailwindcss/postcss': {}, autoprefixer: {}, }, } diff --git a/resources/css/filament/common/tailwind.config.js b/resources/css/filament/common/tailwind.config.js deleted file mode 100644 index 19d2a4cf..00000000 --- a/resources/css/filament/common/tailwind.config.js +++ /dev/null @@ -1,12 +0,0 @@ -import preset from '../../../../vendor/filament/filament/tailwind.config.preset' - -export default { - presets: [preset], - content: [ - './app/Filament/**/*.php', - './resources/views/filament/**/*.blade.php', - './resources/views/**/*.blade.php', - './vendor/filament/**/*.blade.php', - './vendor/awcodes/filament-table-repeater/resources/**/*.blade.php' - ], -} diff --git a/resources/css/filament/common/theme.css b/resources/css/filament/common/theme.css index 27473dd6..ffe14f6d 100644 --- a/resources/css/filament/common/theme.css +++ b/resources/css/filament/common/theme.css @@ -1,27 +1,4 @@ -@import '/vendor/filament/filament/resources/css/theme.css'; -@import '/vendor/awcodes/filament-table-repeater/resources/css/plugin.css'; +@import '../../../../vendor/filament/filament/resources/css/theme.css'; -@config 'tailwind.config.js'; - - -.fi-sidebar-group-label { - @apply uppercase !text-xs tracking-wide; -} - -.fi-in-entry-wrp > .gap-y-2 { - row-gap: 0; -} - -.fi-in-entry-wrp-label > span { - @apply text-xs text-gray-700; -} - -.fi-checkbox-input, -.fi-radio-input { - @apply ring-gray-600; -} - -.fi-radio-input ~ div span, -.fi-checkbox-input ~ span { - @apply font-normal text-gray-600; -} +@source '../../../../app/Filament/Admin/**/*'; +@source '../../../../resources/views/filament/admin/**/*'; diff --git a/resources/views/components/history-line.blade.php b/resources/views/components/history-line.blade.php index d8d2b353..8e6eaa3a 100644 --- a/resources/views/components/history-line.blade.php +++ b/resources/views/components/history-line.blade.php @@ -1,14 +1,14 @@ - - + + {{ $fieldLabel }} - + - + {{ $oldValue }} - + - + {{ $newValue }} - + - + diff --git a/resources/views/filament/organizations/pages/profile/user-personal-info.blade.php b/resources/views/filament/organizations/pages/profile/user-personal-info.blade.php new file mode 100644 index 00000000..287c7500 --- /dev/null +++ b/resources/views/filament/organizations/pages/profile/user-personal-info.blade.php @@ -0,0 +1,10 @@ + + + {{ $this->form }} + + + + diff --git a/resources/views/forms/components/radio-table.blade.php b/resources/views/forms/components/radio-table.blade.php index 0a471dc0..7752501c 100644 --- a/resources/views/forms/components/radio-table.blade.php +++ b/resources/views/forms/components/radio-table.blade.php @@ -5,28 +5,28 @@ :component="$getFieldWrapperView()" >
- - - - + + + + @foreach($getRadioOptions() as $options) - + @endforeach - - - + + + @foreach($getChildComponents() as $radio) - - + + {{-- @foreach($radio->getOptions() as $value => $label)--}} -{{-- --}} +{{-- --}} {{-- @endforeach--}} {{-- {{ $radio->render() }}--}} - + @endforeach - - + +
- + {{ $options }} - +
{{ $radio }} - + --}} {{-- {{ dd($radio->getId()) }}--}} {{-- class(['mt-1'])--}} {{-- "--}} {{-- />--}} -{{-- --}} +{{--
{{--
--}} {{-- --}} diff --git a/resources/views/forms/components/report-table.blade.php b/resources/views/forms/components/report-table.blade.php index 5743cb59..274a4ded 100644 --- a/resources/views/forms/components/report-table.blade.php +++ b/resources/views/forms/components/report-table.blade.php @@ -19,42 +19,43 @@
- - - + + + @foreach($header as $key => $headerElement) @if($key === 0) - {{ $headerElement }} - + @elseif($key === 1 && $subHeader) - + @else - + @endif @endforeach - + @if($subHeader) - + @foreach($subHeader as $subheaderElement) - + @endforeach - + @endif - + + @foreach($verticalHeader as $verticalKey => $header) @if ($verticalSubHeader) @@ -62,19 +63,19 @@ $firstSubHeaderRow = true @endphp @foreach($verticalSubHeader as $verticalSubKey => $subheader) - + @if ($firstSubHeaderRow) - + @endif - + @foreach($subHeader as $key => $subheaderElement) - + @endforeach - + + @php $firstSubHeaderRow = false @endphp @endforeach @elseif ($subHeader) - - + + @foreach($subHeader as $key => $subheaderElement) - + @endforeach - + + @else - - + + - + + @endif @endforeach - - + + @foreach($subHeader as $key => $subheaderElement) - + @endforeach - + + + +
{{ $headerElement }} - + {{ $headerElement }} - +
{{ $subheaderElement }} - +
{{ $header }} - + {{ $subheader }} - + {{ $reportData->filter(function ($item) use ($subHeaderKey, $verticalHeaderKey, $verticalSubHeaderKey, $verticalKey, $verticalSubKey, $key) { $subHeaderField = $key && $item->$subHeaderKey instanceof BackedEnum ? $item->$subHeaderKey->value : @@ -92,10 +93,10 @@ }) ->first()?->total_cases ?? 0 }} - + {{ $reportData->filter(function ($item) use ($verticalHeaderKey,$verticalKey, $verticalSubHeaderKey, $verticalSubKey){ $verticalHeaderKeyValue = $item->$verticalHeaderKey instanceof BackedEnum ? $item->$verticalHeaderKey->value : @@ -107,19 +108,19 @@ $verticalSubHeaderKeyValue == $verticalSubKey; }) ->sum('total_cases') }} - - +
{{ $header }} - + {{ $reportData->filter(function ($item) use ($subHeaderKey, $verticalHeaderKey, $verticalKey, $key) { $subHeaderField = $item->$subHeaderKey instanceof BackedEnum ? $item->$subHeaderKey->value : @@ -133,9 +134,9 @@ }) ->first()?->total_cases ?? 0 }} - + {{ $reportData->filter(function ($item) use ($verticalHeaderKey, $verticalKey) { $verticalHeaderField = $item->$verticalHeaderKey instanceof BackedEnum ? $item->$verticalHeaderKey->value : @@ -145,15 +146,15 @@ }) ->sum('total_cases') }} - - +
{{ $header }} - + {{ $reportData->filter(fn ($item) => $item->$verticalHeaderKey instanceof BackedEnum ? $item->$verticalHeaderKey->value == $verticalKey : @@ -161,32 +162,31 @@ ->first() ?->total_cases ?? 0 }} - - +
{{ $footer }} - + {{ $reportData->filter(function($item) use ($subHeaderKey, $key){ $subHeaderField = $item->$subHeaderKey instanceof BackedEnum ? $item->$subHeaderKey->value : $item->$subHeaderKey; return $subHeaderField == $key; })->sum('total_cases') }} - + {{ $reportData->sum('total_cases') }} - - - - - +