diff --git a/.gitignore b/.gitignore
index 862902c..ebc6cb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ yarn-error.log
/.idea
/.vscode
/relay
+/storage/media-library
diff --git a/.junie/guidelines.md b/.junie/guidelines.md
new file mode 100644
index 0000000..f367dec
--- /dev/null
+++ b/.junie/guidelines.md
@@ -0,0 +1,375 @@
+
+=== foundation rules ===
+
+# Laravel Boost Guidelines
+
+The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
+
+## Foundational Context
+This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
+
+- php - 8.3.29
+- laravel/folio (FOLIO) - v1
+- laravel/framework (LARAVEL) - v11
+- laravel/prompts (PROMPTS) - v0
+- laravel/pulse (PULSE) - v1
+- laravel/reverb (REVERB) - v1
+- laravel/sail (SAIL) - v1
+- laravel/sanctum (SANCTUM) - v4
+- livewire/livewire (LIVEWIRE) - v4
+- laravel/mcp (MCP) - v0
+- laravel/pint (PINT) - v1
+- pestphp/pest (PEST) - v2
+- phpunit/phpunit (PHPUNIT) - v10
+- laravel-echo (ECHO) - v1
+- tailwindcss (TAILWINDCSS) - v3
+
+## 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 it works. Unit and feature tests are more important.
+
+## Application Structure & Architecture
+- Stick to existing directory structure; don't create new base folders without approval.
+- Do not change the application's dependencies without approval.
+
+## Frontend Bundling
+- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `vendor/bin/sail yarn run build`, `vendor/bin/sail yarn run dev`, or `vendor/bin/sail composer run dev`. Ask them.
+
+## Replies
+- Be concise in your explanations - focus on what's important rather than explaining obvious details.
+
+## Documentation Files
+- You must only create documentation files if explicitly requested by the user.
+
+=== boost rules ===
+
+## Laravel Boost
+- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
+
+## Artisan
+- Use the `list-artisan-commands` tool when you need to call an Artisan command to double-check the available parameters.
+
+## URLs
+- Whenever you share a project URL with the user, you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain/IP, and port.
+
+## Tinker / Debugging
+- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
+- Use the `database-query` tool when you only need to read from the database.
+
+## Reading Browser Logs With the `browser-logs` Tool
+- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
+- Only recent browser logs will be useful - ignore old logs.
+
+## Searching Documentation (Critically Important)
+- Boost comes with a powerful `search-docs` tool you should use before any other approaches when dealing 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.
+- The `search-docs` tool is perfect for all Laravel-related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
+- You must use this tool to search for Laravel ecosystem documentation before falling back to other approaches.
+- Search the documentation before making code changes to ensure we are taking the correct approach.
+- Use multiple, broad, simple, topic-based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
+- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
+
+### Available Search Syntax
+- You can and should pass multiple queries at once. The most relevant results will be returned first.
+
+1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'.
+2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit".
+3. Quoted Phrases (Exact Position) - query="infinite scroll" - words must be adjacent and in that order.
+4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit".
+5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms.
+
+=== php rules ===
+
+## PHP
+
+- Always use curly braces for control structures, even if it has one line.
+
+### 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
+{
+ ...
+}
+
+
+## Comments
+- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless there is something very complex going on.
+
+## PHPDoc Blocks
+- Add useful array shape type definitions for arrays when appropriate.
+
+## Enums
+- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
+
+=== sail rules ===
+
+## Laravel Sail
+
+- This project runs inside Laravel Sail's Docker containers. You MUST execute all commands through Sail.
+- Start services using `vendor/bin/sail up -d` and stop them with `vendor/bin/sail stop`.
+- Open the application in the browser by running `vendor/bin/sail open`.
+- Always prefix PHP, Artisan, Composer, and Node commands with `vendor/bin/sail`. Examples:
+ - Run Artisan Commands: `vendor/bin/sail artisan migrate`
+ - Install Composer packages: `vendor/bin/sail composer install`
+ - Execute Node commands: `vendor/bin/sail yarn run dev`
+ - Execute PHP scripts: `vendor/bin/sail php [script]`
+- View all available Sail commands by running `vendor/bin/sail` without arguments.
+
+=== folio/core rules ===
+
+## Laravel Folio
+
+- Laravel Folio is a file-based router. With Laravel Folio, a new route is created for every Blade file within the configured Folio directory. For example, pages are usually in `resources/views/pages/` and the file structure determines routes:
+ - `pages/index.blade.php` → `/`
+ - `pages/profile/index.blade.php` → `/profile`
+ - `pages/auth/login.blade.php` → `/auth/login`
+- You may list available Folio routes using `vendor/bin/sail artisan folio:list` or using the `list-routes` tool.
+
+### New Pages & Routes
+- Always create new `folio` pages and routes using `vendor/bin/sail artisan folio:page [name]` following existing naming conventions.
+
+
+ // Creates: resources/views/pages/products.blade.php → /products
+ vendor/bin/sail artisan folio:page "products"
+
+ // Creates: resources/views/pages/products/[id].blade.php → /products/{id}
+ vendor/bin/sail artisan folio:page "products/[id]"
+
+
+- Add a 'name' to each new Folio page at the very top of the file so it has a named route available for other parts of the codebase to use.
+
+
+use function Laravel\Folio\name;
+
+name('products.index');
+
+
+### Support & Documentation
+- Folio supports: middleware, serving pages from multiple paths, subdomain routing, named routes, nested routes, index routes, route parameters, and route model binding.
+- If available, use the `search-docs` tool to use Folio to its full potential and help the user effectively.
+
+
+use function Laravel\Folio\{name, middleware};
+
+name('admin.products');
+middleware(['auth', 'verified', 'can:manage-products']);
+?>
+
+
+=== laravel/core rules ===
+
+## Do Things the Laravel Way
+
+- Use `vendor/bin/sail 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 `vendor/bin/sail 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 `vendor/bin/sail artisan make:model`.
+
+### APIs & Eloquent Resources
+- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
+
+### Controllers & Validation
+- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
+- Check sibling Form Requests to see if the application uses array or string based validation rules.
+
+### Queues
+- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
+
+### Authentication & Authorization
+- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
+
+### URL Generation
+- When generating links to other pages, prefer named routes and the `route()` function.
+
+### Configuration
+- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
+
+### Testing
+- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
+- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
+- When creating tests, make use of `vendor/bin/sail 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 `vendor/bin/sail yarn run build` or ask the user to run `vendor/bin/sail yarn run dev` or `vendor/bin/sail composer run dev`.
+
+=== laravel/v11 rules ===
+
+## Laravel 11
+
+- Use the `search-docs` tool to get version-specific documentation.
+- Laravel 11 brought a new streamlined file structure which this project now uses.
+
+### Laravel 11 Structure
+- In Laravel 11, middleware are no longer registered in `app/Http/Kernel.php`.
+- Middleware are configured declaratively in `bootstrap/app.php` using `Application::configure()->withMiddleware()`.
+- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
+- `bootstrap/providers.php` contains application specific service providers.
+- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
+- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
+
+### Database
+- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
+- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
+
+### Models
+- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
+
+### New Artisan Commands
+- List Artisan commands using Boost's MCP tool, if available. New commands available in Laravel 11:
+ - `vendor/bin/sail artisan make:enum`
+ - `vendor/bin/sail artisan make:class`
+ - `vendor/bin/sail artisan make:interface`
+
+=== livewire/core rules ===
+
+## Livewire
+
+- Use the `search-docs` tool to find exact version-specific documentation for how to write Livewire and Livewire tests.
+- Use the `vendor/bin/sail artisan make:livewire [Posts\CreatePost]` Artisan command to create new components.
+- State should live on the server, with the UI reflecting it.
+- All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions.
+
+## Livewire Best Practices
+- Livewire components require a single root element.
+- Use `wire:loading` and `wire:dirty` for delightful loading states.
+- Add `wire:key` in loops:
+
+ ```blade
+ @foreach ($items as $item)
+
+ {{ $item->name }}
+
+ @endforeach
+ ```
+
+- Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
+
+
+ public function mount(User $user) { $this->user = $user; }
+ public function updatedSearch() { $this->resetPage(); }
+
+
+## Testing Livewire
+
+
+ Livewire::test(Counter::class)
+ ->assertSet('count', 0)
+ ->call('increment')
+ ->assertSet('count', 1)
+ ->assertSee(1)
+ ->assertStatus(200);
+
+
+
+ $this->get('/posts/create')
+ ->assertSeeLivewire(CreatePost::class);
+
+
+=== pint/core rules ===
+
+## Laravel Pint Code Formatter
+
+- You must run `vendor/bin/sail bin pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
+- Do not run `vendor/bin/sail bin pint --test`, simply run `vendor/bin/sail bin pint` to fix any formatting issues.
+
+=== pest/core rules ===
+
+## Pest
+### Testing
+- If you need to verify a feature is working, write or update a Unit / Feature test.
+
+### Pest Tests
+- All tests must be written using Pest. Use `vendor/bin/sail artisan make:test --pest {name}`.
+- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
+- Tests should test all of the happy paths, failure paths, and weird paths.
+- Tests live in the `tests/Feature` and `tests/Unit` directories.
+- Pest tests look and behave like this:
+
+it('is true', function () {
+ expect(true)->toBeTrue();
+});
+
+
+### Running Tests
+- Run the minimal number of tests using an appropriate filter before finalizing code edits.
+- To run all tests: `vendor/bin/sail artisan test --compact`.
+- To run all tests in a file: `vendor/bin/sail artisan test --compact tests/Feature/ExampleTest.php`.
+- To filter on a particular test name: `vendor/bin/sail artisan test --compact --filter=testName` (recommended after making a change to a related file).
+- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
+
+### Pest Assertions
+- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
+
+it('returns all', function () {
+ $response = $this->postJson('/api/docs', []);
+
+ $response->assertSuccessful();
+});
+
+
+### Mocking
+- Mocking can be very helpful when appropriate.
+- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
+- You can also create partial mocks using the same import or self method.
+
+### Datasets
+- Use datasets in Pest to simplify tests that have a lot of duplicated data. This is often the case when testing validation rules, so consider this solution when writing tests for validation rules.
+
+
+it('has emails', function (string $email) {
+ expect($email)->not->toBeEmpty();
+})->with([
+ 'james' => 'james@laravel.com',
+ 'taylor' => 'taylor@laravel.com',
+]);
+
+
+=== tailwindcss/core rules ===
+
+## Tailwind CSS
+
+- Use Tailwind CSS classes to style HTML; check and use existing Tailwind conventions within the project before writing your own.
+- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc.).
+- Think through class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child carefully to limit repetition, and group elements logically.
+- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
+
+### Spacing
+- When listing items, use gap utilities for spacing; don't use margins.
+
+
+
+
Superior
+
Michigan
+
Erie
+
+
+
+### Dark Mode
+- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
+
+=== tailwindcss/v3 rules ===
+
+## Tailwind CSS 3
+
+- Always use Tailwind CSS v3; verify you're using only classes supported by this version.
+
diff --git a/.junie/mcp/mcp.json b/.junie/mcp/mcp.json
new file mode 100644
index 0000000..04eba29
--- /dev/null
+++ b/.junie/mcp/mcp.json
@@ -0,0 +1,11 @@
+{
+ "mcpServers": {
+ "laravel-boost": {
+ "command": "vendor/bin/sail",
+ "args": [
+ "artisan",
+ "boost:mcp"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/.mcp.json b/.mcp.json
new file mode 100644
index 0000000..04eba29
--- /dev/null
+++ b/.mcp.json
@@ -0,0 +1,11 @@
+{
+ "mcpServers": {
+ "laravel-boost": {
+ "command": "vendor/bin/sail",
+ "args": [
+ "artisan",
+ "boost:mcp"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..f367dec
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,375 @@
+
+=== foundation rules ===
+
+# Laravel Boost Guidelines
+
+The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
+
+## Foundational Context
+This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
+
+- php - 8.3.29
+- laravel/folio (FOLIO) - v1
+- laravel/framework (LARAVEL) - v11
+- laravel/prompts (PROMPTS) - v0
+- laravel/pulse (PULSE) - v1
+- laravel/reverb (REVERB) - v1
+- laravel/sail (SAIL) - v1
+- laravel/sanctum (SANCTUM) - v4
+- livewire/livewire (LIVEWIRE) - v4
+- laravel/mcp (MCP) - v0
+- laravel/pint (PINT) - v1
+- pestphp/pest (PEST) - v2
+- phpunit/phpunit (PHPUNIT) - v10
+- laravel-echo (ECHO) - v1
+- tailwindcss (TAILWINDCSS) - v3
+
+## 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 it works. Unit and feature tests are more important.
+
+## Application Structure & Architecture
+- Stick to existing directory structure; don't create new base folders without approval.
+- Do not change the application's dependencies without approval.
+
+## Frontend Bundling
+- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `vendor/bin/sail yarn run build`, `vendor/bin/sail yarn run dev`, or `vendor/bin/sail composer run dev`. Ask them.
+
+## Replies
+- Be concise in your explanations - focus on what's important rather than explaining obvious details.
+
+## Documentation Files
+- You must only create documentation files if explicitly requested by the user.
+
+=== boost rules ===
+
+## Laravel Boost
+- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
+
+## Artisan
+- Use the `list-artisan-commands` tool when you need to call an Artisan command to double-check the available parameters.
+
+## URLs
+- Whenever you share a project URL with the user, you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain/IP, and port.
+
+## Tinker / Debugging
+- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
+- Use the `database-query` tool when you only need to read from the database.
+
+## Reading Browser Logs With the `browser-logs` Tool
+- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
+- Only recent browser logs will be useful - ignore old logs.
+
+## Searching Documentation (Critically Important)
+- Boost comes with a powerful `search-docs` tool you should use before any other approaches when dealing 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.
+- The `search-docs` tool is perfect for all Laravel-related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
+- You must use this tool to search for Laravel ecosystem documentation before falling back to other approaches.
+- Search the documentation before making code changes to ensure we are taking the correct approach.
+- Use multiple, broad, simple, topic-based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
+- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
+
+### Available Search Syntax
+- You can and should pass multiple queries at once. The most relevant results will be returned first.
+
+1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'.
+2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit".
+3. Quoted Phrases (Exact Position) - query="infinite scroll" - words must be adjacent and in that order.
+4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit".
+5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms.
+
+=== php rules ===
+
+## PHP
+
+- Always use curly braces for control structures, even if it has one line.
+
+### 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
+{
+ ...
+}
+
+
+## Comments
+- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless there is something very complex going on.
+
+## PHPDoc Blocks
+- Add useful array shape type definitions for arrays when appropriate.
+
+## Enums
+- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
+
+=== sail rules ===
+
+## Laravel Sail
+
+- This project runs inside Laravel Sail's Docker containers. You MUST execute all commands through Sail.
+- Start services using `vendor/bin/sail up -d` and stop them with `vendor/bin/sail stop`.
+- Open the application in the browser by running `vendor/bin/sail open`.
+- Always prefix PHP, Artisan, Composer, and Node commands with `vendor/bin/sail`. Examples:
+ - Run Artisan Commands: `vendor/bin/sail artisan migrate`
+ - Install Composer packages: `vendor/bin/sail composer install`
+ - Execute Node commands: `vendor/bin/sail yarn run dev`
+ - Execute PHP scripts: `vendor/bin/sail php [script]`
+- View all available Sail commands by running `vendor/bin/sail` without arguments.
+
+=== folio/core rules ===
+
+## Laravel Folio
+
+- Laravel Folio is a file-based router. With Laravel Folio, a new route is created for every Blade file within the configured Folio directory. For example, pages are usually in `resources/views/pages/` and the file structure determines routes:
+ - `pages/index.blade.php` → `/`
+ - `pages/profile/index.blade.php` → `/profile`
+ - `pages/auth/login.blade.php` → `/auth/login`
+- You may list available Folio routes using `vendor/bin/sail artisan folio:list` or using the `list-routes` tool.
+
+### New Pages & Routes
+- Always create new `folio` pages and routes using `vendor/bin/sail artisan folio:page [name]` following existing naming conventions.
+
+
+ // Creates: resources/views/pages/products.blade.php → /products
+ vendor/bin/sail artisan folio:page "products"
+
+ // Creates: resources/views/pages/products/[id].blade.php → /products/{id}
+ vendor/bin/sail artisan folio:page "products/[id]"
+
+
+- Add a 'name' to each new Folio page at the very top of the file so it has a named route available for other parts of the codebase to use.
+
+
+use function Laravel\Folio\name;
+
+name('products.index');
+
+
+### Support & Documentation
+- Folio supports: middleware, serving pages from multiple paths, subdomain routing, named routes, nested routes, index routes, route parameters, and route model binding.
+- If available, use the `search-docs` tool to use Folio to its full potential and help the user effectively.
+
+
+use function Laravel\Folio\{name, middleware};
+
+name('admin.products');
+middleware(['auth', 'verified', 'can:manage-products']);
+?>
+
+
+=== laravel/core rules ===
+
+## Do Things the Laravel Way
+
+- Use `vendor/bin/sail 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 `vendor/bin/sail 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 `vendor/bin/sail artisan make:model`.
+
+### APIs & Eloquent Resources
+- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
+
+### Controllers & Validation
+- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
+- Check sibling Form Requests to see if the application uses array or string based validation rules.
+
+### Queues
+- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
+
+### Authentication & Authorization
+- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
+
+### URL Generation
+- When generating links to other pages, prefer named routes and the `route()` function.
+
+### Configuration
+- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
+
+### Testing
+- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
+- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
+- When creating tests, make use of `vendor/bin/sail 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 `vendor/bin/sail yarn run build` or ask the user to run `vendor/bin/sail yarn run dev` or `vendor/bin/sail composer run dev`.
+
+=== laravel/v11 rules ===
+
+## Laravel 11
+
+- Use the `search-docs` tool to get version-specific documentation.
+- Laravel 11 brought a new streamlined file structure which this project now uses.
+
+### Laravel 11 Structure
+- In Laravel 11, middleware are no longer registered in `app/Http/Kernel.php`.
+- Middleware are configured declaratively in `bootstrap/app.php` using `Application::configure()->withMiddleware()`.
+- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
+- `bootstrap/providers.php` contains application specific service providers.
+- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
+- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
+
+### Database
+- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
+- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
+
+### Models
+- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
+
+### New Artisan Commands
+- List Artisan commands using Boost's MCP tool, if available. New commands available in Laravel 11:
+ - `vendor/bin/sail artisan make:enum`
+ - `vendor/bin/sail artisan make:class`
+ - `vendor/bin/sail artisan make:interface`
+
+=== livewire/core rules ===
+
+## Livewire
+
+- Use the `search-docs` tool to find exact version-specific documentation for how to write Livewire and Livewire tests.
+- Use the `vendor/bin/sail artisan make:livewire [Posts\CreatePost]` Artisan command to create new components.
+- State should live on the server, with the UI reflecting it.
+- All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions.
+
+## Livewire Best Practices
+- Livewire components require a single root element.
+- Use `wire:loading` and `wire:dirty` for delightful loading states.
+- Add `wire:key` in loops:
+
+ ```blade
+ @foreach ($items as $item)
+
+ {{ $item->name }}
+
+ @endforeach
+ ```
+
+- Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
+
+
+ public function mount(User $user) { $this->user = $user; }
+ public function updatedSearch() { $this->resetPage(); }
+
+
+## Testing Livewire
+
+
+ Livewire::test(Counter::class)
+ ->assertSet('count', 0)
+ ->call('increment')
+ ->assertSet('count', 1)
+ ->assertSee(1)
+ ->assertStatus(200);
+
+
+
+ $this->get('/posts/create')
+ ->assertSeeLivewire(CreatePost::class);
+
+
+=== pint/core rules ===
+
+## Laravel Pint Code Formatter
+
+- You must run `vendor/bin/sail bin pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
+- Do not run `vendor/bin/sail bin pint --test`, simply run `vendor/bin/sail bin pint` to fix any formatting issues.
+
+=== pest/core rules ===
+
+## Pest
+### Testing
+- If you need to verify a feature is working, write or update a Unit / Feature test.
+
+### Pest Tests
+- All tests must be written using Pest. Use `vendor/bin/sail artisan make:test --pest {name}`.
+- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
+- Tests should test all of the happy paths, failure paths, and weird paths.
+- Tests live in the `tests/Feature` and `tests/Unit` directories.
+- Pest tests look and behave like this:
+
+it('is true', function () {
+ expect(true)->toBeTrue();
+});
+
+
+### Running Tests
+- Run the minimal number of tests using an appropriate filter before finalizing code edits.
+- To run all tests: `vendor/bin/sail artisan test --compact`.
+- To run all tests in a file: `vendor/bin/sail artisan test --compact tests/Feature/ExampleTest.php`.
+- To filter on a particular test name: `vendor/bin/sail artisan test --compact --filter=testName` (recommended after making a change to a related file).
+- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
+
+### Pest Assertions
+- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
+
+it('returns all', function () {
+ $response = $this->postJson('/api/docs', []);
+
+ $response->assertSuccessful();
+});
+
+
+### Mocking
+- Mocking can be very helpful when appropriate.
+- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
+- You can also create partial mocks using the same import or self method.
+
+### Datasets
+- Use datasets in Pest to simplify tests that have a lot of duplicated data. This is often the case when testing validation rules, so consider this solution when writing tests for validation rules.
+
+
+it('has emails', function (string $email) {
+ expect($email)->not->toBeEmpty();
+})->with([
+ 'james' => 'james@laravel.com',
+ 'taylor' => 'taylor@laravel.com',
+]);
+
+
+=== tailwindcss/core rules ===
+
+## Tailwind CSS
+
+- Use Tailwind CSS classes to style HTML; check and use existing Tailwind conventions within the project before writing your own.
+- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc.).
+- Think through class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child carefully to limit repetition, and group elements logically.
+- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
+
+### Spacing
+- When listing items, use gap utilities for spacing; don't use margins.
+
+
+
+
Superior
+
Michigan
+
Erie
+
+
+
+### Dark Mode
+- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
+
+=== tailwindcss/v3 rules ===
+
+## Tailwind CSS 3
+
+- Always use Tailwind CSS v3; verify you're using only classes supported by this version.
+
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..f367dec
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,375 @@
+
+=== foundation rules ===
+
+# Laravel Boost Guidelines
+
+The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
+
+## Foundational Context
+This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
+
+- php - 8.3.29
+- laravel/folio (FOLIO) - v1
+- laravel/framework (LARAVEL) - v11
+- laravel/prompts (PROMPTS) - v0
+- laravel/pulse (PULSE) - v1
+- laravel/reverb (REVERB) - v1
+- laravel/sail (SAIL) - v1
+- laravel/sanctum (SANCTUM) - v4
+- livewire/livewire (LIVEWIRE) - v4
+- laravel/mcp (MCP) - v0
+- laravel/pint (PINT) - v1
+- pestphp/pest (PEST) - v2
+- phpunit/phpunit (PHPUNIT) - v10
+- laravel-echo (ECHO) - v1
+- tailwindcss (TAILWINDCSS) - v3
+
+## 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 it works. Unit and feature tests are more important.
+
+## Application Structure & Architecture
+- Stick to existing directory structure; don't create new base folders without approval.
+- Do not change the application's dependencies without approval.
+
+## Frontend Bundling
+- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `vendor/bin/sail yarn run build`, `vendor/bin/sail yarn run dev`, or `vendor/bin/sail composer run dev`. Ask them.
+
+## Replies
+- Be concise in your explanations - focus on what's important rather than explaining obvious details.
+
+## Documentation Files
+- You must only create documentation files if explicitly requested by the user.
+
+=== boost rules ===
+
+## Laravel Boost
+- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
+
+## Artisan
+- Use the `list-artisan-commands` tool when you need to call an Artisan command to double-check the available parameters.
+
+## URLs
+- Whenever you share a project URL with the user, you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain/IP, and port.
+
+## Tinker / Debugging
+- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
+- Use the `database-query` tool when you only need to read from the database.
+
+## Reading Browser Logs With the `browser-logs` Tool
+- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
+- Only recent browser logs will be useful - ignore old logs.
+
+## Searching Documentation (Critically Important)
+- Boost comes with a powerful `search-docs` tool you should use before any other approaches when dealing 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.
+- The `search-docs` tool is perfect for all Laravel-related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
+- You must use this tool to search for Laravel ecosystem documentation before falling back to other approaches.
+- Search the documentation before making code changes to ensure we are taking the correct approach.
+- Use multiple, broad, simple, topic-based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
+- Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
+
+### Available Search Syntax
+- You can and should pass multiple queries at once. The most relevant results will be returned first.
+
+1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'.
+2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit".
+3. Quoted Phrases (Exact Position) - query="infinite scroll" - words must be adjacent and in that order.
+4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit".
+5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms.
+
+=== php rules ===
+
+## PHP
+
+- Always use curly braces for control structures, even if it has one line.
+
+### 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
+{
+ ...
+}
+
+
+## Comments
+- Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless there is something very complex going on.
+
+## PHPDoc Blocks
+- Add useful array shape type definitions for arrays when appropriate.
+
+## Enums
+- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
+
+=== sail rules ===
+
+## Laravel Sail
+
+- This project runs inside Laravel Sail's Docker containers. You MUST execute all commands through Sail.
+- Start services using `vendor/bin/sail up -d` and stop them with `vendor/bin/sail stop`.
+- Open the application in the browser by running `vendor/bin/sail open`.
+- Always prefix PHP, Artisan, Composer, and Node commands with `vendor/bin/sail`. Examples:
+ - Run Artisan Commands: `vendor/bin/sail artisan migrate`
+ - Install Composer packages: `vendor/bin/sail composer install`
+ - Execute Node commands: `vendor/bin/sail yarn run dev`
+ - Execute PHP scripts: `vendor/bin/sail php [script]`
+- View all available Sail commands by running `vendor/bin/sail` without arguments.
+
+=== folio/core rules ===
+
+## Laravel Folio
+
+- Laravel Folio is a file-based router. With Laravel Folio, a new route is created for every Blade file within the configured Folio directory. For example, pages are usually in `resources/views/pages/` and the file structure determines routes:
+ - `pages/index.blade.php` → `/`
+ - `pages/profile/index.blade.php` → `/profile`
+ - `pages/auth/login.blade.php` → `/auth/login`
+- You may list available Folio routes using `vendor/bin/sail artisan folio:list` or using the `list-routes` tool.
+
+### New Pages & Routes
+- Always create new `folio` pages and routes using `vendor/bin/sail artisan folio:page [name]` following existing naming conventions.
+
+
+ // Creates: resources/views/pages/products.blade.php → /products
+ vendor/bin/sail artisan folio:page "products"
+
+ // Creates: resources/views/pages/products/[id].blade.php → /products/{id}
+ vendor/bin/sail artisan folio:page "products/[id]"
+
+
+- Add a 'name' to each new Folio page at the very top of the file so it has a named route available for other parts of the codebase to use.
+
+
+use function Laravel\Folio\name;
+
+name('products.index');
+
+
+### Support & Documentation
+- Folio supports: middleware, serving pages from multiple paths, subdomain routing, named routes, nested routes, index routes, route parameters, and route model binding.
+- If available, use the `search-docs` tool to use Folio to its full potential and help the user effectively.
+
+
+use function Laravel\Folio\{name, middleware};
+
+name('admin.products');
+middleware(['auth', 'verified', 'can:manage-products']);
+?>
+
+
+=== laravel/core rules ===
+
+## Do Things the Laravel Way
+
+- Use `vendor/bin/sail 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 `vendor/bin/sail 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 `vendor/bin/sail artisan make:model`.
+
+### APIs & Eloquent Resources
+- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
+
+### Controllers & Validation
+- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
+- Check sibling Form Requests to see if the application uses array or string based validation rules.
+
+### Queues
+- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
+
+### Authentication & Authorization
+- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
+
+### URL Generation
+- When generating links to other pages, prefer named routes and the `route()` function.
+
+### Configuration
+- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
+
+### Testing
+- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
+- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
+- When creating tests, make use of `vendor/bin/sail 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 `vendor/bin/sail yarn run build` or ask the user to run `vendor/bin/sail yarn run dev` or `vendor/bin/sail composer run dev`.
+
+=== laravel/v11 rules ===
+
+## Laravel 11
+
+- Use the `search-docs` tool to get version-specific documentation.
+- Laravel 11 brought a new streamlined file structure which this project now uses.
+
+### Laravel 11 Structure
+- In Laravel 11, middleware are no longer registered in `app/Http/Kernel.php`.
+- Middleware are configured declaratively in `bootstrap/app.php` using `Application::configure()->withMiddleware()`.
+- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
+- `bootstrap/providers.php` contains application specific service providers.
+- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
+- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
+
+### Database
+- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
+- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
+
+### Models
+- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
+
+### New Artisan Commands
+- List Artisan commands using Boost's MCP tool, if available. New commands available in Laravel 11:
+ - `vendor/bin/sail artisan make:enum`
+ - `vendor/bin/sail artisan make:class`
+ - `vendor/bin/sail artisan make:interface`
+
+=== livewire/core rules ===
+
+## Livewire
+
+- Use the `search-docs` tool to find exact version-specific documentation for how to write Livewire and Livewire tests.
+- Use the `vendor/bin/sail artisan make:livewire [Posts\CreatePost]` Artisan command to create new components.
+- State should live on the server, with the UI reflecting it.
+- All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions.
+
+## Livewire Best Practices
+- Livewire components require a single root element.
+- Use `wire:loading` and `wire:dirty` for delightful loading states.
+- Add `wire:key` in loops:
+
+ ```blade
+ @foreach ($items as $item)
+
+ {{ $item->name }}
+
+ @endforeach
+ ```
+
+- Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
+
+
+ public function mount(User $user) { $this->user = $user; }
+ public function updatedSearch() { $this->resetPage(); }
+
+
+## Testing Livewire
+
+
+ Livewire::test(Counter::class)
+ ->assertSet('count', 0)
+ ->call('increment')
+ ->assertSet('count', 1)
+ ->assertSee(1)
+ ->assertStatus(200);
+
+
+
+ $this->get('/posts/create')
+ ->assertSeeLivewire(CreatePost::class);
+
+
+=== pint/core rules ===
+
+## Laravel Pint Code Formatter
+
+- You must run `vendor/bin/sail bin pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
+- Do not run `vendor/bin/sail bin pint --test`, simply run `vendor/bin/sail bin pint` to fix any formatting issues.
+
+=== pest/core rules ===
+
+## Pest
+### Testing
+- If you need to verify a feature is working, write or update a Unit / Feature test.
+
+### Pest Tests
+- All tests must be written using Pest. Use `vendor/bin/sail artisan make:test --pest {name}`.
+- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
+- Tests should test all of the happy paths, failure paths, and weird paths.
+- Tests live in the `tests/Feature` and `tests/Unit` directories.
+- Pest tests look and behave like this:
+
+it('is true', function () {
+ expect(true)->toBeTrue();
+});
+
+
+### Running Tests
+- Run the minimal number of tests using an appropriate filter before finalizing code edits.
+- To run all tests: `vendor/bin/sail artisan test --compact`.
+- To run all tests in a file: `vendor/bin/sail artisan test --compact tests/Feature/ExampleTest.php`.
+- To filter on a particular test name: `vendor/bin/sail artisan test --compact --filter=testName` (recommended after making a change to a related file).
+- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
+
+### Pest Assertions
+- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
+
+it('returns all', function () {
+ $response = $this->postJson('/api/docs', []);
+
+ $response->assertSuccessful();
+});
+
+
+### Mocking
+- Mocking can be very helpful when appropriate.
+- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
+- You can also create partial mocks using the same import or self method.
+
+### Datasets
+- Use datasets in Pest to simplify tests that have a lot of duplicated data. This is often the case when testing validation rules, so consider this solution when writing tests for validation rules.
+
+
+it('has emails', function (string $email) {
+ expect($email)->not->toBeEmpty();
+})->with([
+ 'james' => 'james@laravel.com',
+ 'taylor' => 'taylor@laravel.com',
+]);
+
+
+=== tailwindcss/core rules ===
+
+## Tailwind CSS
+
+- Use Tailwind CSS classes to style HTML; check and use existing Tailwind conventions within the project before writing your own.
+- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc.).
+- Think through class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child carefully to limit repetition, and group elements logically.
+- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
+
+### Spacing
+- When listing items, use gap utilities for spacing; don't use margins.
+
+
+
+
Superior
+
Michigan
+
Erie
+
+
+
+### Dark Mode
+- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
+
+=== tailwindcss/v3 rules ===
+
+## Tailwind CSS 3
+
+- Always use Tailwind CSS v3; verify you're using only classes supported by this version.
+
diff --git a/app/Livewire/Association/Election/Admin.php b/app/Livewire/Association/Election/Admin.php
new file mode 100644
index 0000000..35e93b8
--- /dev/null
+++ b/app/Livewire/Association/Election/Admin.php
@@ -0,0 +1,171 @@
+ 'handleNostrLoggedOut',
+ 'nostrLoggedIn' => 'handleNostrLoggedIn',
+ 'echo:votes,.newVote' => 'handleNewVote',
+ ];
+
+ public function mount(Election $election): void
+ {
+ $this->election = $election;
+ $this->loadEvents();
+ $this->loadBoardEvents();
+ $this->loadVotes();
+ $this->loadBoardVotes();
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ $this->currentPubkey = $pubkey;
+ $allowedPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ ];
+ if (in_array($this->currentPubkey, $allowedPubkeys, true)) {
+ $this->isAllowed = true;
+ }
+ dd($this->isAllowed);
+ }
+
+ public function handleNewVote(): void
+ {
+ $this->loadEvents();
+ $this->loadBoardEvents();
+ $this->loadVotes();
+ $this->loadBoardVotes();
+ }
+
+ public function loadVotes(): void
+ {
+ $this->votes = collect($this->events)
+ ->map(fn ($event) => [
+ 'created_at' => $event['created_at'],
+ 'pubkey' => $event['pubkey'],
+ 'forpubkey' => $this->fetchProfile($event['content']),
+ 'type' => str($event['content'])->after(',')->toString(),
+ ])
+ ->sortByDesc('created_at')
+ ->unique(fn ($event) => $event['pubkey'].$event['type'])
+ ->values()
+ ->groupBy('type')
+ ->map(fn ($votes) => [
+ 'type' => $votes[0]['type'],
+ 'votes' => $votes->groupBy('forpubkey')->map(fn ($group) => ['count' => $group->count()])->toArray(),
+ ])
+ ->values()
+ ->toArray();
+ }
+
+ public function loadBoardVotes(): void
+ {
+ $this->boardVotes = collect($this->boardEvents)
+ ->map(fn ($event) => [
+ 'created_at' => $event['created_at'],
+ 'pubkey' => $event['pubkey'],
+ 'forpubkey' => $this->fetchProfile($event['content']),
+ 'type' => str($event['content'])->after(',')->toString(),
+ ])
+ ->sortByDesc('created_at')
+ ->values()
+ ->groupBy('type')
+ ->map(fn ($votes) => [
+ 'type' => $votes[0]['type'],
+ 'votes' => $votes->groupBy('forpubkey')->map(fn ($group) => ['count' => $group->count()])->toArray(),
+ ])
+ ->values()
+ ->toArray();
+ }
+
+ public function loadEvents(): void
+ {
+ $this->events = $this->loadNostrEvents([32122]);
+ }
+
+ public function loadBoardEvents(): void
+ {
+ $this->boardEvents = $this->loadNostrEvents([2121]);
+ }
+
+ public function fetchProfile($content): string
+ {
+ $pubkey = str($content)->before(',')->toString();
+ $profile = \App\Models\Profile::query()->where('pubkey', $pubkey)->first();
+ if (! $profile) {
+ \Artisan::call(\App\Console\Commands\Nostr\FetchProfile::class, ['--pubkey' => $pubkey]);
+ $profile = \App\Models\Profile::query()->where('pubkey', $pubkey)->first();
+ }
+
+ return $profile->pubkey;
+ }
+
+ public function loadNostrEvents($kinds): array
+ {
+ $subscription = new Subscription;
+ $subscriptionId = $subscription->setId();
+ $filter = new Filter;
+ $filter->setKinds($kinds);
+ $requestMessage = new RequestMessage($subscriptionId, [$filter]);
+ $relaySet = new RelaySet;
+ $relaySet->setRelays([new Relay(config('services.relay'))]);
+ $request = new Request($relaySet, $requestMessage);
+ $response = $request->send();
+
+ return collect($response[config('services.relay')])
+ ->map(function ($event) {
+ if (! isset($event->event)) {
+ return false;
+ }
+
+ return [
+ 'id' => $event->event->id,
+ 'kind' => $event->event->kind,
+ 'content' => $event->event->content,
+ 'pubkey' => $event->event->pubkey,
+ 'tags' => $event->event->tags,
+ 'created_at' => $event->event->created_at,
+ ];
+ })
+ ->filter()
+ ->toArray();
+ }
+}
diff --git a/app/Livewire/Association/Election/Index.php b/app/Livewire/Association/Election/Index.php
new file mode 100644
index 0000000..eb4c3be
--- /dev/null
+++ b/app/Livewire/Association/Election/Index.php
@@ -0,0 +1,71 @@
+ 'handleNostrLoggedOut',
+ 'nostrLoggedIn' => 'handleNostrLoggedIn',
+ ];
+
+ public function mount(): void
+ {
+ $this->elections = Election::query()
+ ->get()
+ ->toArray();
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $logPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ ];
+ if (in_array($this->currentPubkey, $logPubkeys, true)) {
+ $this->isAllowed = true;
+ }
+ }
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
+ ->where('pubkey', $pubkey)->first();
+ $logPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ ];
+ if (in_array($this->currentPubkey, $logPubkeys, true)) {
+ $this->isAllowed = true;
+ }
+ }
+
+ public function saveElection($index): void
+ {
+ $election = $this->elections[$index];
+ $electionModel = Election::find($election['id']);
+ $electionModel->candidates = $election['candidates'];
+ $electionModel->save();
+ }
+}
diff --git a/app/Livewire/Association/Election/Show.php b/app/Livewire/Association/Election/Show.php
new file mode 100644
index 0000000..b6e0185
--- /dev/null
+++ b/app/Livewire/Association/Election/Show.php
@@ -0,0 +1,186 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ 'echo:votes,.newVote' => 'handleNewVote',
+ ];
+
+ public function mount(Election $election): void
+ {
+ $this->election = $election;
+ $this->plebs = EinundzwanzigPleb::query()
+ ->with(['profile'])
+ ->whereIn('association_status', [3, 4])
+ ->orderBy('association_status', 'desc')
+ ->get()
+ ->toArray();
+ $this->loadEvents();
+ $this->loadBoardEvents();
+ if ($this->election->end_time?->isPast() || ! config('services.voting')) {
+ $this->isNotClosed = false;
+ }
+ }
+
+ public function updatedSearch($value): void
+ {
+ $this->plebs = EinundzwanzigPleb::query()
+ ->with(['profile'])
+ ->whereIn('association_status', [3, 4])
+ ->where(fn ($query) => $query
+ ->where('pubkey', 'like', "%$value%")
+ ->orWhereHas('profile', fn ($query) => $query->where('name', 'ilike', "%$value%")))
+ ->orderBy('association_status', 'desc')
+ ->get()
+ ->toArray();
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ $logPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ ];
+ if (in_array($this->currentPubkey, $logPubkeys, true)) {
+ $this->showLog = true;
+ $this->isAllowed = true;
+ }
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function handleNewVote(): void
+ {
+ $this->loadEvents();
+ $this->loadBoardEvents();
+ }
+
+ public function loadEvents(): void
+ {
+ $this->events = $this->loadNostrEvents([32122]);
+ }
+
+ public function loadBoardEvents(): void
+ {
+ $this->boardEvents = $this->loadNostrEvents([2121]);
+ }
+
+ public function loadNostrEvents($kinds): array
+ {
+ $subscription = new Subscription;
+ $subscriptionId = $subscription->setId();
+ $filter = new Filter;
+ $filter->setKinds($kinds);
+ $requestMessage = new RequestMessage($subscriptionId, [$filter]);
+ $relaySet = new RelaySet;
+ $relaySet->setRelays([new Relay(config('services.relay'))]);
+ $request = new Request($relaySet, $requestMessage);
+ $response = $request->send();
+
+ return collect($response[config('services.relay')])
+ ->map(function ($event) {
+ if (! isset($event->event)) {
+ return false;
+ }
+
+ return [
+ 'id' => $event->event->id,
+ 'kind' => $event->event->kind,
+ 'content' => $event->event->content,
+ 'pubkey' => $event->event->pubkey,
+ 'tags' => $event->event->tags,
+ 'created_at' => $event->event->created_at,
+ ];
+ })
+ ->filter()
+ ->toArray();
+ }
+
+ public function vote($pubkey, $type, $board = false): void
+ {
+ if ($this->election->end_time?->isPast()) {
+ $this->isNotClosed = false;
+
+ return;
+ }
+ $note = new NostrEvent;
+ $note->setKind($board ? 2121 : 32122);
+ if (! $board) {
+ $dTag = sprintf('%s,%s,%s', $this->currentPleb->pubkey, date('Y'), $type);
+ $note->setTags([['d', $dTag]]);
+ }
+ $note->setContent("$pubkey,$type");
+ $this->signThisEvent = $note->toJson();
+ }
+
+ public function checkElection(): void
+ {
+ if ($this->election->end_time?->isPast()) {
+ $this->isNotClosed = false;
+ }
+ }
+
+ public function signEvent($event): void
+ {
+ $note = new NostrEvent;
+ $note->setId($event['id']);
+ $note->setSignature($event['sig']);
+ $note->setKind($event['kind']);
+ $note->setContent($event['content']);
+ $note->setPublicKey($event['pubkey']);
+ $note->setTags($event['tags']);
+ $note->setCreatedAt($event['created_at']);
+ $eventMessage = new EventMessage($note);
+ $relay = new Relay(config('services.relay'));
+ $relay->setMessage($eventMessage);
+ $relay->send();
+ \App\Support\Broadcast::on('votes')->as('newVote')->sendNow();
+ }
+}
diff --git a/app/Livewire/Association/Members/Admin.php b/app/Livewire/Association/Members/Admin.php
new file mode 100644
index 0000000..3935a3a
--- /dev/null
+++ b/app/Livewire/Association/Members/Admin.php
@@ -0,0 +1,66 @@
+ 'handleNostrLoggedOut',
+ 'nostrLoggedIn' => 'handleNostrLoggedIn',
+ ];
+
+ public function mount(): void
+ {
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
+ ->where('pubkey', $this->currentPubkey)->first();
+ $allowedPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
+ 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
+ '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
+ 'acbcec475a1a4f9481939ecfbd1c3d111f5b5a474a39ae039bbc720fdd305bec',
+ ];
+ if (in_array($this->currentPubkey, $allowedPubkeys, true)) {
+ $this->isAllowed = true;
+ }
+ }
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
+ ->where('pubkey', $pubkey)->first();
+ $allowedPubkeys = [
+ '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
+ '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
+ '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
+ 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
+ '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
+ 'acbcec475a1a4f9481939ecfbd1c3d111f5b5a474a39ae039bbc720fdd305bec',
+ ];
+ if (in_array($this->currentPubkey, $allowedPubkeys, true)) {
+ $this->isAllowed = true;
+ }
+ }
+}
diff --git a/app/Livewire/Association/News/Index.php b/app/Livewire/Association/News/Index.php
new file mode 100644
index 0000000..64e1664
--- /dev/null
+++ b/app/Livewire/Association/News/Index.php
@@ -0,0 +1,122 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(): void
+ {
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
+ if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) {
+ $this->canEdit = true;
+ }
+ $this->isAllowed = true;
+ }
+ $this->refreshNews();
+ }
+
+ public function refreshNews(): void
+ {
+ $this->news = Notification::query()
+ ->orderBy('created_at', 'desc')
+ ->get();
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) {
+ $this->canEdit = true;
+ }
+ $this->isAllowed = true;
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function save(): void
+ {
+ $this->form->validate();
+
+ $this->validate([
+ 'file' => 'required|file|mimes:pdf|max:1024',
+ ]);
+
+ $notification = Notification::query()
+ ->orderBy('created_at', 'desc')
+ ->create([
+ 'einundzwanzig_pleb_id' => $this->currentPleb->id,
+ 'category' => $this->form->category,
+ 'name' => $this->form->name,
+ 'description' => $this->form->description,
+ ]);
+
+ $notification
+ ->addMedia($this->file->getRealPath())
+ ->usingName($this->file->getClientOriginalName())
+ ->toMediaCollection('pdf');
+
+ $this->form->reset();
+ $this->file = null;
+
+ $this->refreshNews();
+ }
+
+ public function delete($id): void
+ {
+ $notification = new WireNotification($this);
+ $notification->confirm([
+ 'title' => 'Post löschen',
+ 'message' => 'Bist du sicher, dass du diesen Post löschen möchtest?',
+ 'accept' => [
+ 'label' => 'Ja, löschen',
+ 'method' => 'deleteNow',
+ 'params' => $id,
+ ],
+ ]);
+ }
+
+ public function deleteNow($id): void
+ {
+ $notification = Notification::query()->find($id);
+ $notification->delete();
+ $this->refreshNews();
+ }
+}
diff --git a/app/Livewire/Association/Profile.php b/app/Livewire/Association/Profile.php
new file mode 100644
index 0000000..19288fe
--- /dev/null
+++ b/app/Livewire/Association/Profile.php
@@ -0,0 +1,304 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(): void
+ {
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = EinundzwanzigPleb::query()
+ ->with([
+ 'paymentEvents' => fn ($query) => $query->where('year', date('Y')),
+ ])
+ ->where('pubkey', $this->currentPubkey)->first();
+ $this->email = $this->currentPleb->email;
+ $this->no = $this->currentPleb->no_email;
+ $this->showEmail = ! $this->no;
+ if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) {
+ $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
+ }
+ if ($this->currentPleb->paymentEvents->count() < 1) {
+ $this->createPaymentEvent();
+ $this->currentPleb->load('paymentEvents');
+ }
+ $this->loadEvents();
+ $this->listenForPayment();
+ }
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = EinundzwanzigPleb::query()
+ ->with([
+ 'paymentEvents' => fn ($query) => $query->where('year', date('Y')),
+ ])
+ ->where('pubkey', $pubkey)->first();
+ $this->email = $this->currentPleb->email;
+ $this->no = $this->currentPleb->no_email;
+ $this->showEmail = ! $this->no;
+ if ($this->currentPleb->association_status === AssociationStatus::ACTIVE) {
+ $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
+ }
+ if ($this->currentPleb->paymentEvents->count() < 1) {
+ $this->createPaymentEvent();
+ $this->currentPleb->load('paymentEvents');
+ }
+ $this->loadEvents();
+ $this->listenForPayment();
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ NostrAuth::logout();
+
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ $this->yearsPaid = [];
+ $this->events = [];
+ $this->payments = [];
+ $this->qrCode = null;
+ $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
+ $this->currentYearIsPaid = false;
+ }
+
+ public function updatedNo(): void
+ {
+ $this->showEmail = ! $this->no;
+ $this->currentPleb->update([
+ 'no_email' => $this->no,
+ ]);
+ }
+
+ public function updatedFax(): void
+ {
+ $this->js('alert("Markus Turm wird sich per Fax melden!")');
+ }
+
+ public function saveEmail(): void
+ {
+ $this->validate([
+ 'email' => 'required|email',
+ ]);
+ $this->currentPleb->update([
+ 'email' => $this->email,
+ ]);
+ $notification = new Notification($this);
+ $notification->success('E-Mail Adresse gespeichert.');
+ }
+
+ public function pay($comment): \Illuminate\Http\RedirectResponse
+ {
+ $paymentEvent = $this->currentPleb
+ ->paymentEvents()
+ ->where('year', date('Y'))
+ ->first();
+ if ($paymentEvent->btc_pay_invoice) {
+ return redirect('https://pay.einundzwanzig.space/i/'.$paymentEvent->btc_pay_invoice);
+ }
+ try {
+ $response = \Illuminate\Support\Facades\Http::withHeaders([
+ 'Authorization' => 'token '.config('services.btc_pay.api_key'),
+ ])->post(
+ 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices',
+ [
+ 'amount' => $this->amountToPay,
+ 'metadata' => [
+ 'orderId' => $comment,
+ 'orderUrl' => url()->route('association.profile'),
+ 'itemDesc' => 'Mitgliedsbeitrag '.date('Y').' von nostr:'.$this->currentPleb->npub,
+ 'posData' => [
+ 'event' => $paymentEvent->event_id,
+ 'pubkey' => $this->currentPleb->pubkey,
+ 'npub' => $this->currentPleb->npub,
+ ],
+ ],
+ 'checkout' => [
+ 'expirationMinutes' => 60 * 24,
+ 'redirectURL' => url()->route('association.profile'),
+ 'redirectAutomatically' => true,
+ 'defaultLanguage' => 'de',
+ ],
+ ],
+ )->throw();
+ $paymentEvent->btc_pay_invoice = $response->json()['id'];
+ $paymentEvent->save();
+
+ return redirect($response->json()['checkoutLink']);
+ } catch (\Exception $e) {
+ $notification = new Notification($this);
+ $notification->error(
+ 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: '.$e->getMessage(),
+ );
+ }
+ }
+
+ public function listenForPayment(): void
+ {
+ $paymentEvent = $this->currentPleb
+ ->paymentEvents()
+ ->where('year', date('Y'))
+ ->first();
+ if ($paymentEvent->btc_pay_invoice) {
+ $response = \Illuminate\Support\Facades\Http::withHeaders([
+ 'Authorization' => 'token '.config('services.btc_pay.api_key'),
+ ])
+ ->get(
+ 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/'.$paymentEvent->btc_pay_invoice,
+ );
+ if ($response->json()['status'] === 'Expired') {
+ $paymentEvent->btc_pay_invoice = null;
+ $paymentEvent->paid = false;
+ $paymentEvent->save();
+ }
+ if ($response->json()['status'] === 'Settled') {
+ $paymentEvent->paid = true;
+ $paymentEvent->save();
+ $this->currentYearIsPaid = true;
+ }
+ }
+ if ($paymentEvent->paid) {
+ $this->currentYearIsPaid = true;
+ }
+ $paymentEvent = $paymentEvent->refresh();
+ $this->payments = $this->currentPleb
+ ->paymentEvents()
+ ->where('paid', true)
+ ->get();
+ }
+
+ public function save($type): void
+ {
+ $this->form->validate();
+ if (! $this->form->check) {
+ $this->js('alert("Du musst den Statuten zustimmen.")');
+
+ return;
+ }
+
+ $this->currentPleb
+ ->update([
+ 'association_status' => $type,
+ ]);
+ }
+
+ public function createPaymentEvent(): void
+ {
+ $note = new NostrEvent;
+ $note->setKind(32121);
+ $note->setContent(
+ 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr '.date(
+ 'Y',
+ ).'. Bitte bezahle den Betrag von '.number_format($this->amountToPay, 0, ',', '.').' Satoshis.',
+ );
+ $note->setTags([
+ ['d', $this->currentPleb->pubkey.','.date('Y')],
+ ['zap', 'daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6', config('services.relay'), '1'],
+ ]);
+ $signer = new Sign;
+ $signer->signEvent($note, config('services.nostr'));
+
+ $eventMessage = new EventMessage($note);
+
+ $relayUrl = config('services.relay');
+ $relay = new Relay($relayUrl);
+ $relay->setMessage($eventMessage);
+ $result = $relay->send();
+
+ $this->currentPleb->paymentEvents()->create([
+ 'year' => date('Y'),
+ 'event_id' => $result->eventId,
+ 'amount' => $this->amountToPay,
+ ]);
+ }
+
+ public function loadEvents(): void
+ {
+ $subscription = new Subscription;
+ $subscriptionId = $subscription->setId();
+
+ $filter1 = new Filter;
+ $filter1->setKinds([32121]);
+ $filter1->setAuthors(['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6']);
+ $filters = [$filter1];
+
+ $requestMessage = new RequestMessage($subscriptionId, $filters);
+
+ $relays = [
+ new Relay(config('services.relay')),
+ ];
+ $relaySet = new RelaySet;
+ $relaySet->setRelays($relays);
+
+ $request = new Request($relaySet, $requestMessage);
+ $response = $request->send();
+
+ $this->events = collect($response[config('services.relay')])
+ ->map(function ($event) {
+ if (! isset($event->event)) {
+ return false;
+ }
+
+ return [
+ 'id' => $event->event->id,
+ 'kind' => $event->event->kind,
+ 'content' => $event->event->content,
+ 'pubkey' => $event->event->pubkey,
+ 'tags' => $event->event->tags,
+ 'created_at' => $event->event->created_at,
+ ];
+ })
+ ->filter()
+ ->unique('id')
+ ->toArray();
+ }
+}
diff --git a/app/Livewire/Association/ProjectSupport/Form/Create.php b/app/Livewire/Association/ProjectSupport/Form/Create.php
new file mode 100644
index 0000000..96c4f7c
--- /dev/null
+++ b/app/Livewire/Association/ProjectSupport/Form/Create.php
@@ -0,0 +1,70 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(): void
+ {
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
+ $this->isAllowed = true;
+ }
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ $this->isAllowed = true;
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function save(): \Illuminate\Http\RedirectResponse
+ {
+ $this->form->validate();
+
+ $projectProposal = \App\Models\ProjectProposal::query()->create([
+ ...$this->form->all(),
+ 'einundzwanzig_pleb_id' => $this->currentPleb->id,
+ ]);
+ if ($this->image) {
+ $this->validate([
+ 'image' => 'image|max:1024',
+ ]);
+ $projectProposal
+ ->addMedia($this->image->getRealPath())
+ ->toMediaCollection('main');
+ }
+
+ return redirect()->route('association.projectSupport');
+ }
+}
diff --git a/app/Livewire/Association/ProjectSupport/Form/Edit.php b/app/Livewire/Association/ProjectSupport/Form/Edit.php
new file mode 100644
index 0000000..781c3b6
--- /dev/null
+++ b/app/Livewire/Association/ProjectSupport/Form/Edit.php
@@ -0,0 +1,75 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(ProjectProposal $projectProposal): void
+ {
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
+ $this->isAllowed = true;
+ $this->form->fill($projectProposal->toArray());
+ $this->projectProposal = $projectProposal;
+ $this->image = $projectProposal->getFirstMedia('main');
+ }
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ $this->isAllowed = true;
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function save(): \Illuminate\Http\RedirectResponse
+ {
+ $this->form->validate();
+ if ($this->image && method_exists($this->image, 'temporaryUrl')) {
+ $this->validate([
+ 'image' => 'nullable|image|max:1024',
+ ]);
+ $this->projectProposal
+ ->addMedia($this->image->getRealPath())
+ ->toMediaCollection('main');
+ }
+
+ $this->projectProposal->update([
+ ...$this->form->except('id', 'slug'),
+ ]);
+
+ return redirect()->route('association.projectSupport');
+ }
+}
diff --git a/app/Livewire/Association/ProjectSupport/Index.php b/app/Livewire/Association/ProjectSupport/Index.php
new file mode 100644
index 0000000..4c64dc1
--- /dev/null
+++ b/app/Livewire/Association/ProjectSupport/Index.php
@@ -0,0 +1,102 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(): void
+ {
+ $this->loadProjects();
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
+ $this->isAllowed = true;
+ }
+ }
+
+ public function updatedSearch(): void
+ {
+ $this->loadProjects();
+ }
+
+ public function loadProjects(): void
+ {
+ $this->projects = ProjectProposal::query()
+ ->with([
+ 'einundzwanzigPleb.profile',
+ 'votes',
+ ])
+ ->where(function ($query) {
+ $query
+ ->where('name', 'ilike', '%'.$this->search.'%')
+ ->orWhere('description', 'ilike', '%'.$this->search.'%')
+ ->orWhereHas('einundzwanzigPleb.profile', function ($q) {
+ $q->where('name', 'ilike', '%'.$this->search.'%');
+ });
+ })
+ ->orderBy('created_at', 'desc')
+ ->get();
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ NostrAuth::login($pubkey);
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ $this->isAllowed = true;
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function confirmDelete($id): void
+ {
+ $notification = new Notification($this);
+ $notification->confirm([
+ 'title' => 'Projektunterstützung löschen',
+ 'message' => 'Bist du sicher, dass du diese Projektunterstützung löschen möchtest?',
+ 'accept' => [
+ 'label' => 'Ja, löschen',
+ 'method' => 'delete',
+ 'params' => $id,
+ ],
+ ]);
+ }
+
+ public function setFilter($filter): void
+ {
+ $this->activeFilter = $filter;
+ }
+
+ public function delete($id): void
+ {
+ ProjectProposal::query()->findOrFail($id)->delete();
+ $this->loadProjects();
+ }
+}
diff --git a/app/Livewire/Association/ProjectSupport/Show.php b/app/Livewire/Association/ProjectSupport/Show.php
new file mode 100644
index 0000000..0dab2d1
--- /dev/null
+++ b/app/Livewire/Association/ProjectSupport/Show.php
@@ -0,0 +1,109 @@
+ 'handleNostrLoggedIn',
+ 'nostrLoggedOut' => 'handleNostrLoggedOut',
+ ];
+
+ public function mount(ProjectProposal $projectProposal): void
+ {
+ $this->projectProposal = $projectProposal;
+ if (NostrAuth::check()) {
+ $this->currentPubkey = NostrAuth::pubkey();
+ $this->handleNostrLoggedIn($this->currentPubkey);
+ }
+ $this->boardVotes = $this->getBoardVotes();
+ $this->otherVotes = $this->getOtherVotes();
+ }
+
+ public function handleNostrLoggedIn($pubkey): void
+ {
+ $this->currentPubkey = $pubkey;
+ $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
+ $this->isAllowed = true;
+ $this->ownVoteExists = Vote::query()
+ ->where('project_proposal_id', $this->projectProposal->id)
+ ->where('einundzwanzig_pleb_id', $this->currentPleb->id)
+ ->exists();
+ }
+
+ public function handleNostrLoggedOut(): void
+ {
+ $this->isAllowed = false;
+ $this->currentPubkey = null;
+ $this->currentPleb = null;
+ }
+
+ public function getBoardVotes(): \Illuminate\Database\Eloquent\Collection
+ {
+ return Vote::query()
+ ->where('project_proposal_id', $this->projectProposal->id)
+ ->whereHas('einundzwanzigPleb', fn ($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board')))
+ ->get();
+ }
+
+ public function getOtherVotes(): \Illuminate\Database\Eloquent\Collection
+ {
+ return Vote::query()
+ ->where('project_proposal_id', $this->projectProposal->id)
+ ->whereDoesntHave(
+ 'einundzwanzigPleb',
+ fn ($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board'))
+ )
+ ->get();
+ }
+
+ public function approve(): void
+ {
+ Vote::query()->updateOrCreate([
+ 'project_proposal_id' => $this->projectProposal->id,
+ 'einundzwanzig_pleb_id' => $this->currentPleb->id,
+ ], [
+ 'value' => true,
+ ]);
+ $this->form->reset();
+ $this->ownVoteExists = true;
+ $this->boardVotes = $this->getBoardVotes();
+ $this->otherVotes = $this->getOtherVotes();
+ }
+
+ public function notApprove(): void
+ {
+ $this->form->validate();
+
+ Vote::query()->updateOrCreate([
+ 'project_proposal_id' => $this->projectProposal->id,
+ 'einundzwanzig_pleb_id' => $this->currentPleb->id,
+ ], [
+ 'value' => false,
+ ]);
+ $this->form->reset();
+ $this->ownVoteExists = true;
+ }
+}
diff --git a/app/Livewire/Changelog.php b/app/Livewire/Changelog.php
new file mode 100644
index 0000000..46e63bb
--- /dev/null
+++ b/app/Livewire/Changelog.php
@@ -0,0 +1,28 @@
+ $hash,
+ 'message' => $message,
+ 'author' => $author,
+ 'date' => $date,
+ ];
+ }
+ $this->entries = $entries;
+ }
+}
diff --git a/app/Livewire/EinundzwanzigFeed/Index.php b/app/Livewire/EinundzwanzigFeed/Index.php
new file mode 100644
index 0000000..595d6ba
--- /dev/null
+++ b/app/Livewire/EinundzwanzigFeed/Index.php
@@ -0,0 +1,51 @@
+events = Event::query()
+ ->where('type', 'root')
+ ->orderBy('created_at', 'desc')
+ ->with([
+ 'renderedEvent',
+ ])
+ ->get()
+ ->toArray();
+ }
+
+ public function hydrate(): void
+ {
+ if ($this->newEvents) {
+ $this->loadMore();
+ }
+ }
+
+ #[Rule('echo:events,.newEvents')]
+ public function updated(): void
+ {
+ $this->newEvents = true;
+ }
+
+ public function loadMore(): void
+ {
+ $this->newEvents = false;
+ $this->events = Event::query()
+ ->where('type', 'root')
+ ->orderBy('created_at', 'desc')
+ ->with([
+ 'renderedEvent',
+ ])
+ ->get()
+ ->toArray();
+ }
+}
diff --git a/app/Livewire/Meetups/Grid.php b/app/Livewire/Meetups/Grid.php
new file mode 100644
index 0000000..5eef74c
--- /dev/null
+++ b/app/Livewire/Meetups/Grid.php
@@ -0,0 +1,10 @@
+loadEvents();
+ }
+
+ public function loadEvents(): void
+ {
+ $subscription = new Subscription;
+ $subscriptionId = $subscription->setId();
+
+ $filter1 = new Filter;
+ $filter1->setKinds([31924]);
+ $filter1->setLimit(25);
+ $filters = [$filter1];
+
+ $requestMessage = new RequestMessage($subscriptionId, $filters);
+
+ $relays = [
+ new Relay('ws://nostream:8008'),
+ ];
+ $relaySet = new RelaySet;
+ $relaySet->setRelays($relays);
+
+ $request = new Request($relaySet, $requestMessage);
+ $response = $request->send();
+
+ $this->events = collect($response['ws://nostream:8008'])
+ ->map(function ($event) {
+ if (! isset($event->event)) {
+ return false;
+ }
+
+ return [
+ 'id' => $event->event->id,
+ 'kind' => $event->event->kind,
+ 'content' => $event->event->content,
+ 'pubkey' => $event->event->pubkey,
+ 'tags' => $event->event->tags,
+ 'created_at' => $event->event->created_at,
+ ];
+ })
+ ->filter()
+ ->toArray();
+ }
+
+ public function save(): void
+ {
+ $note = new NostrEvent;
+ $note->setContent($this->description);
+ $note->setKind(31924);
+ $note->setTags([
+ ['d', str()->uuid()->toString()],
+ ['title', $this->title],
+ ]);
+ $this->signThisEvent = $note->toJson();
+ }
+
+ public function signEvent($event): void
+ {
+ $note = new NostrEvent;
+ $note->setId($event['id']);
+ $note->setSignature($event['sig']);
+ $note->setKind($event['kind']);
+ $note->setContent($event['content']);
+ $note->setPublicKey($event['pubkey']);
+ $note->setTags($event['tags']);
+ $note->setCreatedAt($event['created_at']);
+ $eventMessage = new EventMessage($note);
+ $relayUrl = 'ws://nostream:8008';
+ $relay = new Relay($relayUrl);
+ $relay->setMessage($eventMessage);
+ $relay->send();
+
+ $this->title = '';
+ $this->description = '';
+ $this->loadEvents();
+ }
+}
diff --git a/app/Livewire/Meetups/Table.php b/app/Livewire/Meetups/Table.php
new file mode 100644
index 0000000..0685fbd
--- /dev/null
+++ b/app/Livewire/Meetups/Table.php
@@ -0,0 +1,10 @@
+markers = [];
+ }
+
+ public function filterByMarker($id): void
+ {
+ //
+ }
+}
diff --git a/app/Livewire/Welcome.php b/app/Livewire/Welcome.php
new file mode 100644
index 0000000..403d86c
--- /dev/null
+++ b/app/Livewire/Welcome.php
@@ -0,0 +1,10 @@
+=8.1"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-deprecation-rules": "^2.0",
+ "phpunit/phpunit": "~12.4"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/functions.php"
+ ],
+ "psr-4": {
+ "ChaCha20\\": "lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Leigh",
+ "homepage": "https://github.com/lt"
+ },
+ {
+ "name": "Djuri Baars",
+ "homepage": "https://github.com/dsbaars"
+ }
+ ],
+ "description": "Pure PHP implementation of the ChaCha20 encryption algorithm.",
+ "homepage": "https://github.com/dsbaars/PHP-ChaCha20",
+ "keywords": [
+ "cipher",
+ "encryption",
+ "security",
+ "stream"
+ ],
+ "support": {
+ "source": "https://github.com/dsbaars/PHP-ChaCha20/tree/0.3.0"
+ },
+ "time": "2025-11-28T16:51:46+00:00"
+ },
{
"name": "egulias/email-validator",
"version": "4.0.4",
@@ -1134,31 +1192,31 @@
},
{
"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": {
@@ -1189,7 +1247,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": [
{
@@ -1201,24 +1259,24 @@
"type": "github"
}
],
- "time": "2023-10-12T05:21:21+00:00"
+ "time": "2025-12-03T09:33:47+00:00"
},
{
"name": "genkgo/php-asn1",
- "version": "v2.8.0",
+ "version": "v2.9.0",
"source": {
"type": "git",
"url": "https://github.com/genkgo/php-asn1.git",
- "reference": "4de712c68bbf51c00551cb45f55642e30fed1fdb"
+ "reference": "dc535345d0ecc69181c6a1e17e57a625bd01f891"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/genkgo/php-asn1/zipball/4de712c68bbf51c00551cb45f55642e30fed1fdb",
- "reference": "4de712c68bbf51c00551cb45f55642e30fed1fdb",
+ "url": "https://api.github.com/repos/genkgo/php-asn1/zipball/dc535345d0ecc69181c6a1e17e57a625bd01f891",
+ "reference": "dc535345d0ecc69181c6a1e17e57a625bd01f891",
"shasum": ""
},
"require": {
- "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
+ "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "~2.0",
@@ -1279,30 +1337,30 @@
],
"support": {
"issues": "https://github.com/genkgo/php-asn1/issues",
- "source": "https://github.com/genkgo/php-asn1/tree/v2.8.0"
+ "source": "https://github.com/genkgo/php-asn1/tree/v2.9.0"
},
- "time": "2025-02-12T20:20:53+00:00"
+ "time": "2026-01-06T11:43:05+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": {
@@ -1331,7 +1389,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": [
{
@@ -1343,7 +1401,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:45:45+00:00"
+ "time": "2025-12-27T19:43:20+00:00"
},
{
"name": "guzzlehttp/guzzle",
@@ -1818,16 +1876,16 @@
},
{
"name": "laravel/folio",
- "version": "v1.1.11",
+ "version": "v1.1.12",
"source": {
"type": "git",
"url": "https://github.com/laravel/folio.git",
- "reference": "8233c26268a04a828c34e37d5fc185248f932b4b"
+ "reference": "8ada43c28f9da9bcf71cd1a8c933007b6f906599"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/folio/zipball/8233c26268a04a828c34e37d5fc185248f932b4b",
- "reference": "8233c26268a04a828c34e37d5fc185248f932b4b",
+ "url": "https://api.github.com/repos/laravel/folio/zipball/8ada43c28f9da9bcf71cd1a8c933007b6f906599",
+ "reference": "8ada43c28f9da9bcf71cd1a8c933007b6f906599",
"shasum": ""
},
"require": {
@@ -1844,8 +1902,8 @@
"symfony/console": "^6.0|^7.0"
},
"require-dev": {
- "orchestra/testbench": "^8.6.0|^9.0|^10.0",
- "pestphp/pest": "^2.5|^3.0",
+ "orchestra/testbench": "^8.36|^9.15|^10.8",
+ "pestphp/pest": "^2.5|^3.0|^4.0",
"phpstan/phpstan": "^1.10"
},
"type": "library",
@@ -1887,20 +1945,20 @@
"issues": "https://github.com/laravel/folio/issues",
"source": "https://github.com/laravel/folio"
},
- "time": "2025-11-05T15:47:07+00:00"
+ "time": "2025-11-25T14:45:02+00:00"
},
{
"name": "laravel/framework",
- "version": "v11.46.1",
+ "version": "v11.47.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "5fd457f807570a962a53b403b1346efe4cc80bb8"
+ "reference": "86693ffa1ba32f56f8c44e31416c6665095a62c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/5fd457f807570a962a53b403b1346efe4cc80bb8",
- "reference": "5fd457f807570a962a53b403b1346efe4cc80bb8",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/86693ffa1ba32f56f8c44e31416c6665095a62c5",
+ "reference": "86693ffa1ba32f56f8c44e31416c6665095a62c5",
"shasum": ""
},
"require": {
@@ -2102,25 +2160,25 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2025-09-30T14:51:32+00:00"
+ "time": "2025-11-28T18:20:11+00:00"
},
{
"name": "laravel/prompts",
- "version": "v0.1.25",
+ "version": "v0.3.10",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95"
+ "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/7b4029a84c37cb2725fc7f011586e2997040bc95",
- "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/360ba095ef9f51017473505191fbd4ab73e1cab3",
+ "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3",
"shasum": ""
},
"require": {
+ "composer-runtime-api": "^2.2",
"ext-mbstring": "*",
- "illuminate/collections": "^10.0|^11.0",
"php": "^8.1",
"symfony/console": "^6.2|^7.0"
},
@@ -2129,10 +2187,11 @@
"laravel/framework": ">=10.17.0 <10.25.0"
},
"require-dev": {
+ "illuminate/collections": "^10.0|^11.0|^12.0",
"mockery/mockery": "^1.5",
- "pestphp/pest": "^2.3",
- "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."
@@ -2140,7 +2199,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "0.1.x-dev"
+ "dev-main": "0.3.x-dev"
}
},
"autoload": {
@@ -2158,22 +2217,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.1.25"
+ "source": "https://github.com/laravel/prompts/tree/v0.3.10"
},
- "time": "2024-08-12T22:06:33+00:00"
+ "time": "2026-01-13T20:29:29+00:00"
},
{
"name": "laravel/pulse",
- "version": "v1.4.3",
+ "version": "v1.5.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pulse.git",
- "reference": "8c57f30aa6e094c138cd191314fe060d60773c14"
+ "reference": "ee70e069f0386060bc668d3b63a30bae403d0485"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pulse/zipball/8c57f30aa6e094c138cd191314fe060d60773c14",
- "reference": "8c57f30aa6e094c138cd191314fe060d60773c14",
+ "url": "https://api.github.com/repos/laravel/pulse/zipball/ee70e069f0386060bc668d3b63a30bae403d0485",
+ "reference": "ee70e069f0386060bc668d3b63a30bae403d0485",
"shasum": ""
},
"require": {
@@ -2192,7 +2251,7 @@
"illuminate/routing": "^10.48.4|^11.0.8|^12.0",
"illuminate/support": "^10.48.4|^11.0.8|^12.0",
"illuminate/view": "^10.48.4|^11.0.8|^12.0",
- "livewire/livewire": "^3.6.4",
+ "livewire/livewire": "^3.6.4|^4.0",
"nesbot/carbon": "^2.67|^3.0",
"php": "^8.1",
"symfony/console": "^6.0|^7.0"
@@ -2203,9 +2262,9 @@
"require-dev": {
"guzzlehttp/guzzle": "^7.7",
"mockery/mockery": "^1.0",
- "orchestra/testbench": "^8.23.1|^9.0|^10.0",
- "pestphp/pest": "^2.0",
- "pestphp/pest-plugin-laravel": "^2.2",
+ "orchestra/testbench": "^8.36|^9.15|^10.8",
+ "pestphp/pest": "^2.0|^3.0|^4.0",
+ "pestphp/pest-plugin-laravel": "^2.2|^3.0|^4.0",
"phpstan/phpstan": "^1.12.21",
"predis/predis": "^1.0|^2.0"
},
@@ -2247,20 +2306,20 @@
"issues": "https://github.com/laravel/pulse/issues",
"source": "https://github.com/laravel/pulse"
},
- "time": "2025-07-18T15:54:11+00:00"
+ "time": "2026-01-14T22:52:32+00:00"
},
{
"name": "laravel/reverb",
- "version": "v1.6.1",
+ "version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/reverb.git",
- "reference": "a85ba34d2e23cc4a356296363e9a14dfefc4ac8f"
+ "reference": "4300fbbc3535f5cbbdf600b00edca1e4c515bfcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/reverb/zipball/a85ba34d2e23cc4a356296363e9a14dfefc4ac8f",
- "reference": "a85ba34d2e23cc4a356296363e9a14dfefc4ac8f",
+ "url": "https://api.github.com/repos/laravel/reverb/zipball/4300fbbc3535f5cbbdf600b00edca1e4c515bfcf",
+ "reference": "4300fbbc3535f5cbbdf600b00edca1e4c515bfcf",
"shasum": ""
},
"require": {
@@ -2280,8 +2339,8 @@
"symfony/http-foundation": "^6.3|^7.0"
},
"require-dev": {
- "orchestra/testbench": "^8.0|^9.0|^10.0",
- "pestphp/pest": "^2.0|^3.0",
+ "orchestra/testbench": "^8.36|^9.15|^10.8",
+ "pestphp/pest": "^2.0|^3.0|^4.0",
"phpstan/phpstan": "^1.10",
"ratchet/pawl": "^0.4.1",
"react/async": "^4.2",
@@ -2327,22 +2386,22 @@
],
"support": {
"issues": "https://github.com/laravel/reverb/issues",
- "source": "https://github.com/laravel/reverb/tree/v1.6.1"
+ "source": "https://github.com/laravel/reverb/tree/v1.7.0"
},
- "time": "2025-11-11T22:48:00+00:00"
+ "time": "2026-01-06T16:26:25+00:00"
},
{
"name": "laravel/sail",
- "version": "v1.48.1",
+ "version": "v1.52.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/sail.git",
- "reference": "ef122b223f5fca5e5d88bda5127c846710886329"
+ "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/sail/zipball/ef122b223f5fca5e5d88bda5127c846710886329",
- "reference": "ef122b223f5fca5e5d88bda5127c846710886329",
+ "url": "https://api.github.com/repos/laravel/sail/zipball/64ac7d8abb2dbcf2b76e61289451bae79066b0b3",
+ "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3",
"shasum": ""
},
"require": {
@@ -2392,20 +2451,20 @@
"issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail"
},
- "time": "2025-11-17T22:05:34+00:00"
+ "time": "2026-01-01T02:46:03+00:00"
},
{
"name": "laravel/sanctum",
- "version": "v4.2.0",
+ "version": "v4.2.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
- "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677"
+ "reference": "47d26f1d310879ff757b971f5a6fc631d18663fd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
- "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
+ "url": "https://api.github.com/repos/laravel/sanctum/zipball/47d26f1d310879ff757b971f5a6fc631d18663fd",
+ "reference": "47d26f1d310879ff757b971f5a6fc631d18663fd",
"shasum": ""
},
"require": {
@@ -2419,9 +2478,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": {
@@ -2456,20 +2514,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-11T18:20:25+00:00"
},
{
"name": "laravel/serializable-closure",
- "version": "v2.0.6",
+ "version": "v2.0.8",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "038ce42edee619599a1debb7e81d7b3759492819"
+ "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/038ce42edee619599a1debb7e81d7b3759492819",
- "reference": "038ce42edee619599a1debb7e81d7b3759492819",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b",
+ "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b",
"shasum": ""
},
"require": {
@@ -2478,7 +2536,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"
},
@@ -2517,20 +2575,20 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2025-10-09T13:42:30+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": {
@@ -2539,7 +2597,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",
@@ -2581,22 +2639,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": {
@@ -2633,7 +2691,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "2.8-dev"
+ "dev-main": "2.9-dev"
}
},
"autoload": {
@@ -2690,7 +2748,7 @@
"type": "tidelift"
}
],
- "time": "2025-07-20T12:47:49+00:00"
+ "time": "2025-11-26T21:48:24+00:00"
},
{
"name": "league/config",
@@ -2964,20 +3022,20 @@
},
{
"name": "league/uri",
- "version": "7.6.0",
+ "version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri.git",
- "reference": "f625804987a0a9112d954f9209d91fec52182344"
+ "reference": "4436c6ec8d458e4244448b069cc572d088230b76"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri/zipball/f625804987a0a9112d954f9209d91fec52182344",
- "reference": "f625804987a0a9112d954f9209d91fec52182344",
+ "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
+ "reference": "4436c6ec8d458e4244448b069cc572d088230b76",
"shasum": ""
},
"require": {
- "league/uri-interfaces": "^7.6",
+ "league/uri-interfaces": "^7.8",
"php": "^8.1",
"psr/http-factory": "^1"
},
@@ -2991,11 +3049,11 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"ext-uri": "to use the PHP native URI class",
- "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
- "league/uri-components": "Needed to easily manipulate URI objects components",
- "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
+ "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 WHATWG URL",
+ "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",
@@ -3050,7 +3108,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.6.0"
+ "source": "https://github.com/thephpleague/uri/tree/7.8.0"
},
"funding": [
{
@@ -3058,20 +3116,20 @@
"type": "github"
}
],
- "time": "2025-11-18T12:17:23+00:00"
+ "time": "2026-01-14T17:24:56+00:00"
},
{
"name": "league/uri-interfaces",
- "version": "7.6.0",
+ "version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git",
- "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368"
+ "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/ccbfb51c0445298e7e0b7f4481b942f589665368",
- "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368",
+ "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
+ "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
"shasum": ""
},
"require": {
@@ -3084,7 +3142,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 WHATWG URL",
+ "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",
@@ -3134,7 +3192,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.6.0"
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
},
"funding": [
{
@@ -3142,74 +3200,20 @@
"type": "github"
}
],
- "time": "2025-11-18T12:17:23+00:00"
- },
- {
- "name": "leigh/chacha20",
- "version": "0.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/lt/PHP-ChaCha20.git",
- "reference": "7aeffd53228be384b4a8986c9a8d9578acb171a4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/lt/PHP-ChaCha20/zipball/7aeffd53228be384b4a8986c9a8d9578acb171a4",
- "reference": "7aeffd53228be384b4a8986c9a8d9578acb171a4",
- "shasum": ""
- },
- "require": {
- "php": ">=7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~5.0"
- },
- "type": "library",
- "autoload": {
- "files": [
- "lib/functions.php"
- ],
- "psr-4": {
- "ChaCha20\\": "lib"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Leigh",
- "homepage": "https://github.com/lt"
- }
- ],
- "description": "Pure PHP implementation of the ChaCha20 encryption algorithm.",
- "homepage": "https://github.com/lt/PHP-ChaCha20",
- "keywords": [
- "cipher",
- "encryption",
- "security",
- "stream"
- ],
- "support": {
- "issues": "https://github.com/lt/PHP-ChaCha20/issues",
- "source": "https://github.com/lt/PHP-ChaCha20/tree/0.2.0"
- },
- "abandoned": true,
- "time": "2016-01-14T11:24:17+00:00"
+ "time": "2026-01-15T06:54:53+00:00"
},
{
"name": "livewire/livewire",
- "version": "v3.6.4",
+ "version": "v4.0.1",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
- "reference": "ef04be759da41b14d2d129e670533180a44987dc"
+ "reference": "c7539589d5af82691bef17da17ce4e289269f8d9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc",
- "reference": "ef04be759da41b14d2d129e670533180a44987dc",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/c7539589d5af82691bef17da17ce4e289269f8d9",
+ "reference": "c7539589d5af82691bef17da17ce4e289269f8d9",
"shasum": ""
},
"require": {
@@ -3264,7 +3268,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/v4.0.1"
},
"funding": [
{
@@ -3272,92 +3276,20 @@
"type": "github"
}
],
- "time": "2025-07-17T05:12:15+00:00"
- },
- {
- "name": "livewire/volt",
- "version": "v1.10.0",
- "source": {
- "type": "git",
- "url": "https://github.com/livewire/volt.git",
- "reference": "79a5e2367944aad6f4af9edef31a3d688cc8875c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/livewire/volt/zipball/79a5e2367944aad6f4af9edef31a3d688cc8875c",
- "reference": "79a5e2367944aad6f4af9edef31a3d688cc8875c",
- "shasum": ""
- },
- "require": {
- "laravel/framework": "^10.38.2|^11.0|^12.0",
- "livewire/livewire": "^3.6.1|^4.0",
- "php": "^8.1"
- },
- "require-dev": {
- "laravel/folio": "^1.1",
- "mockery/mockery": "^1.6",
- "orchestra/testbench": "^8.15.0|^9.0|^10.0",
- "pestphp/pest": "^2.9.5|^3.0",
- "phpstan/phpstan": "^1.10"
- },
- "type": "library",
- "extra": {
- "laravel": {
- "providers": [
- "Livewire\\Volt\\VoltServiceProvider"
- ]
- },
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "files": [
- "functions.php"
- ],
- "psr-4": {
- "Livewire\\Volt\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
- },
- {
- "name": "Nuno Maduro",
- "email": "nuno@laravel.com"
- }
- ],
- "description": "An elegantly crafted functional API for Laravel Livewire.",
- "homepage": "https://github.com/livewire/volt",
- "keywords": [
- "laravel",
- "livewire",
- "volt"
- ],
- "support": {
- "issues": "https://github.com/livewire/volt/issues",
- "source": "https://github.com/livewire/volt"
- },
- "time": "2025-11-14T15:10:57+00:00"
+ "time": "2026-01-14T18:40:41+00:00"
},
{
"name": "maennchen/zipstream-php",
- "version": "3.2.0",
+ "version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
- "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416"
+ "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9712d8fa4cdf9240380b01eb4be55ad8dcf71416",
- "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/682f1098a8fddbaf43edac2306a691c7ad508ec5",
+ "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5",
"shasum": ""
},
"require": {
@@ -3368,7 +3300,7 @@
"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",
@@ -3414,7 +3346,7 @@
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
- "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.0"
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.1"
},
"funding": [
{
@@ -3422,20 +3354,20 @@
"type": "github"
}
],
- "time": "2025-07-17T11:15:13+00:00"
+ "time": "2025-12-10T09:58:31+00:00"
},
{
"name": "monolog/monolog",
- "version": "3.9.0",
+ "version": "3.10.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
+ "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0"
},
"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": {
@@ -3453,7 +3385,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",
@@ -3513,7 +3445,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": [
{
@@ -3525,20 +3457,20 @@
"type": "tidelift"
}
],
- "time": "2025-03-24T10:02:05+00:00"
+ "time": "2026-01-02T08:56:05+00:00"
},
{
"name": "nesbot/carbon",
- "version": "3.10.3",
+ "version": "3.11.0",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
- "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f"
+ "reference": "bdb375400dcd162624531666db4799b36b64e4a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f",
- "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1",
+ "reference": "bdb375400dcd162624531666db4799b36b64e4a1",
"shasum": ""
},
"require": {
@@ -3546,9 +3478,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"
@@ -3630,7 +3562,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-06T13:39:36+00:00"
+ "time": "2025-12-02T21:04:28+00:00"
},
{
"name": "nette/schema",
@@ -3699,20 +3631,20 @@
},
{
"name": "nette/utils",
- "version": "v4.0.8",
+ "version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede"
+ "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede",
- "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede",
+ "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72",
+ "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72",
"shasum": ""
},
"require": {
- "php": "8.0 - 8.5"
+ "php": "8.2 - 8.5"
},
"conflict": {
"nette/finder": "<3",
@@ -3735,7 +3667,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.1-dev"
}
},
"autoload": {
@@ -3782,22 +3714,22 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
- "source": "https://github.com/nette/utils/tree/v4.0.8"
+ "source": "https://github.com/nette/utils/tree/v4.1.1"
},
- "time": "2025-08-06T21:43:34+00:00"
+ "time": "2025-12-22T12:14:32+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.6.2",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "3a454ca033b9e06b63282ce19562e892747449bb"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
- "reference": "3a454ca033b9e06b63282ce19562e892747449bb",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -3840,9 +3772,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
},
- "time": "2025-10-21T19:32:17+00:00"
+ "time": "2025-12-06T11:56:16+00:00"
},
{
"name": "nunomaduro/termwind",
@@ -4325,16 +4257,16 @@
},
{
"name": "paragonie/sodium_compat",
- "version": "v2.4.0",
+ "version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/sodium_compat.git",
- "reference": "547e2dc4d45107440e76c17ab5a46e4252460158"
+ "reference": "4714da6efdc782c06690bc72ce34fae7941c2d9f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/547e2dc4d45107440e76c17ab5a46e4252460158",
- "reference": "547e2dc4d45107440e76c17ab5a46e4252460158",
+ "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/4714da6efdc782c06690bc72ce34fae7941c2d9f",
+ "reference": "4714da6efdc782c06690bc72ce34fae7941c2d9f",
"shasum": ""
},
"require": {
@@ -4415,22 +4347,22 @@
],
"support": {
"issues": "https://github.com/paragonie/sodium_compat/issues",
- "source": "https://github.com/paragonie/sodium_compat/tree/v2.4.0"
+ "source": "https://github.com/paragonie/sodium_compat/tree/v2.5.0"
},
- "time": "2025-10-06T08:47:40+00:00"
+ "time": "2025-12-30T16:12:18+00:00"
},
{
"name": "phpoption/phpoption",
- "version": "1.9.4",
+ "version": "1.9.5",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
- "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d"
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
- "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be",
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
"shasum": ""
},
"require": {
@@ -4480,7 +4412,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
- "source": "https://github.com/schmittjoh/php-option/tree/1.9.4"
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
},
"funding": [
{
@@ -4492,30 +4424,30 @@
"type": "tidelift"
}
],
- "time": "2025-08-21T11:53:16+00:00"
+ "time": "2025-12-27T19:41:33+00:00"
},
{
"name": "phrity/comparison",
- "version": "1.4.0",
+ "version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/phrity-comparison.git",
- "reference": "aedd44d59db08de7d6c31812d1490c22aab35c92"
+ "reference": "cf80abb822537eeaaeb4142157cd667ca6372a13"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/phrity-comparison/zipball/aedd44d59db08de7d6c31812d1490c22aab35c92",
- "reference": "aedd44d59db08de7d6c31812d1490c22aab35c92",
+ "url": "https://api.github.com/repos/sirn-se/phrity-comparison/zipball/cf80abb822537eeaaeb4142157cd667ca6372a13",
+ "reference": "cf80abb822537eeaaeb4142157cd667ca6372a13",
"shasum": ""
},
"require": {
"php": "^8.1"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
- "squizlabs/php_codesniffer": "^3.5"
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
+ "robiningelbrecht/phpunit-coverage-tools": "^1.9",
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"type": "library",
"autoload": {
@@ -4546,35 +4478,35 @@
],
"support": {
"issues": "https://github.com/sirn-se/phrity-comparison/issues",
- "source": "https://github.com/sirn-se/phrity-comparison/tree/1.4.0"
+ "source": "https://github.com/sirn-se/phrity-comparison/tree/1.4.1"
},
- "time": "2025-05-26T20:12:39+00:00"
+ "time": "2025-12-05T07:38:30+00:00"
},
{
"name": "phrity/http",
- "version": "1.0.0",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/phrity-http.git",
- "reference": "536e3e46e6220d171a59599ed1f4da9f6b6244fc"
+ "reference": "1e7eee67359287b94aae2b7d40b730d5f5394943"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/phrity-http/zipball/536e3e46e6220d171a59599ed1f4da9f6b6244fc",
- "reference": "536e3e46e6220d171a59599ed1f4da9f6b6244fc",
+ "url": "https://api.github.com/repos/sirn-se/phrity-http/zipball/1e7eee67359287b94aae2b7d40b730d5f5394943",
+ "reference": "1e7eee67359287b94aae2b7d40b730d5f5394943",
"shasum": ""
},
"require": {
"php": "^8.1",
"psr/http-factory": "^1.0",
- "psr/http-message": "^1.1 | ^2.0"
+ "psr/http-message": "^1.1 || ^2.0"
},
"require-dev": {
"guzzlehttp/psr7": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
"robiningelbrecht/phpunit-coverage-tools": "^1.9",
- "squizlabs/php_codesniffer": "^3.5"
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"type": "library",
"autoload": {
@@ -4597,41 +4529,43 @@
"homepage": "https://phrity.sirn.se/http",
"keywords": [
"HTTP Factories",
+ "HTTP Serializer",
"http",
- "psr-17"
+ "psr-17",
+ "psr-7"
],
"support": {
"issues": "https://github.com/sirn-se/phrity-http/issues",
- "source": "https://github.com/sirn-se/phrity-http/tree/1.0.0"
+ "source": "https://github.com/sirn-se/phrity-http/tree/1.1.0"
},
- "time": "2025-09-07T17:04:26+00:00"
+ "time": "2025-12-22T20:22:29+00:00"
},
{
"name": "phrity/net-stream",
- "version": "2.3.1",
+ "version": "2.3.3",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/phrity-net-stream.git",
- "reference": "c621bb3108a5a02bba64df2e5f0cd7ada02665b5"
+ "reference": "f46694e1b721867ec3c19731a7fcbbead3c6ac89"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/phrity-net-stream/zipball/c621bb3108a5a02bba64df2e5f0cd7ada02665b5",
- "reference": "c621bb3108a5a02bba64df2e5f0cd7ada02665b5",
+ "url": "https://api.github.com/repos/sirn-se/phrity-net-stream/zipball/f46694e1b721867ec3c19731a7fcbbead3c6ac89",
+ "reference": "f46694e1b721867ec3c19731a7fcbbead3c6ac89",
"shasum": ""
},
"require": {
"php": "^8.1",
"phrity/util-errorhandler": "^1.1",
"psr/http-factory": "^1.0",
- "psr/http-message": "^1.1 | ^2.0"
+ "psr/http-message": "^1.1 || ^2.0"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
"phrity/net-uri": "^2.0",
- "squizlabs/php_codesniffer": "^3.5"
+ "robiningelbrecht/phpunit-coverage-tools": "^1.9",
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"type": "library",
"autoload": {
@@ -4663,22 +4597,22 @@
],
"support": {
"issues": "https://github.com/sirn-se/phrity-net-stream/issues",
- "source": "https://github.com/sirn-se/phrity-net-stream/tree/2.3.1"
+ "source": "https://github.com/sirn-se/phrity-net-stream/tree/2.3.3"
},
- "time": "2025-08-08T09:51:04+00:00"
+ "time": "2025-12-24T12:07:07+00:00"
},
{
"name": "phrity/net-uri",
- "version": "2.2.0",
+ "version": "2.2.1",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/phrity-net-uri.git",
- "reference": "08de4cf07e439c4708f572249659f09198ac99f0"
+ "reference": "0737de026b75177ae302ac9fdbbd0ffc2610f3b8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/phrity-net-uri/zipball/08de4cf07e439c4708f572249659f09198ac99f0",
- "reference": "08de4cf07e439c4708f572249659f09198ac99f0",
+ "url": "https://api.github.com/repos/sirn-se/phrity-net-uri/zipball/0737de026b75177ae302ac9fdbbd0ffc2610f3b8",
+ "reference": "0737de026b75177ae302ac9fdbbd0ffc2610f3b8",
"shasum": ""
},
"require": {
@@ -4689,11 +4623,11 @@
"psr/http-message": "^1.1 | ^2.0"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
"phrity/util-errorhandler": "^1.1",
- "squizlabs/php_codesniffer": "^3.5"
+ "robiningelbrecht/phpunit-coverage-tools": "^1.9",
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"suggest": {
"ext-intl": "Enables IDN conversion for non-ASCII domains"
@@ -4725,32 +4659,32 @@
],
"support": {
"issues": "https://github.com/sirn-se/phrity-net-uri/issues",
- "source": "https://github.com/sirn-se/phrity-net-uri/tree/2.2.0"
+ "source": "https://github.com/sirn-se/phrity-net-uri/tree/2.2.1"
},
- "time": "2025-05-25T13:05:13+00:00"
+ "time": "2025-12-05T10:39:22+00:00"
},
{
"name": "phrity/util-errorhandler",
- "version": "1.2.1",
+ "version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/phrity-util-errorhandler.git",
- "reference": "9825f15ef9b4a93252ce53ca8962278832d834da"
+ "reference": "70a669cc22db2eed6a109ec66fd95168a4332c9b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/phrity-util-errorhandler/zipball/9825f15ef9b4a93252ce53ca8962278832d834da",
- "reference": "9825f15ef9b4a93252ce53ca8962278832d834da",
+ "url": "https://api.github.com/repos/sirn-se/phrity-util-errorhandler/zipball/70a669cc22db2eed6a109ec66fd95168a4332c9b",
+ "reference": "70a669cc22db2eed6a109ec66fd95168a4332c9b",
"shasum": ""
},
"require": {
"php": "^8.1"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
- "squizlabs/php_codesniffer": "^3.5"
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
+ "robiningelbrecht/phpunit-coverage-tools": "^1.9",
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"type": "library",
"autoload": {
@@ -4777,22 +4711,22 @@
],
"support": {
"issues": "https://github.com/sirn-se/phrity-util-errorhandler/issues",
- "source": "https://github.com/sirn-se/phrity-util-errorhandler/tree/1.2.1"
+ "source": "https://github.com/sirn-se/phrity-util-errorhandler/tree/1.2.2"
},
- "time": "2025-08-08T09:48:45+00:00"
+ "time": "2025-12-05T21:25:36+00:00"
},
{
"name": "phrity/websocket",
- "version": "3.6.0",
+ "version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/sirn-se/websocket-php.git",
- "reference": "3f16b2564a230bbce716cccaff2f6156a60a8798"
+ "reference": "b9816ed2b4a10c8c42bd0b6398044ab506869756"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirn-se/websocket-php/zipball/3f16b2564a230bbce716cccaff2f6156a60a8798",
- "reference": "3f16b2564a230bbce716cccaff2f6156a60a8798",
+ "url": "https://api.github.com/repos/sirn-se/websocket-php/zipball/b9816ed2b4a10c8c42bd0b6398044ab506869756",
+ "reference": "b9816ed2b4a10c8c42bd0b6398044ab506869756",
"shasum": ""
},
"require": {
@@ -4801,18 +4735,17 @@
"phrity/net-stream": "^2.3",
"phrity/net-uri": "^2.1",
"psr/http-message": "^1.1 | ^2.0",
- "psr/log": "^1.0 | ^2.0 | ^3.0"
+ "psr/log": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"guzzlehttp/psr7": "^2.0",
- "php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
"phrity/logger-console": "^1.0",
"phrity/net-mock": "^2.3",
"phrity/util-errorhandler": "^1.1",
"robiningelbrecht/phpunit-coverage-tools": "^1.9",
- "squizlabs/php_codesniffer": "^3.5"
+ "squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"type": "library",
"autoload": {
@@ -4843,41 +4776,38 @@
],
"support": {
"issues": "https://github.com/sirn-se/websocket-php/issues",
- "source": "https://github.com/sirn-se/websocket-php/tree/3.6.0"
+ "source": "https://github.com/sirn-se/websocket-php/tree/3.6.2"
},
- "time": "2025-09-08T16:21:41+00:00"
+ "time": "2025-12-21T09:58:16+00:00"
},
{
"name": "power-components/livewire-powergrid",
- "version": "v5.10.7",
+ "version": "v6.7.5",
"source": {
"type": "git",
"url": "https://github.com/Power-Components/livewire-powergrid.git",
- "reference": "98690cdb62ceafd46984f210688b4fb28bb432c1"
+ "reference": "be620d2aa125816195abb7756a57ddaf3849ab40"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Power-Components/livewire-powergrid/zipball/98690cdb62ceafd46984f210688b4fb28bb432c1",
- "reference": "98690cdb62ceafd46984f210688b4fb28bb432c1",
+ "url": "https://api.github.com/repos/Power-Components/livewire-powergrid/zipball/be620d2aa125816195abb7756a57ddaf3849ab40",
+ "reference": "be620d2aa125816195abb7756a57ddaf3849ab40",
"shasum": ""
},
"require": {
- "laravel/prompts": "^0.1.15",
- "livewire/livewire": "^3.4.6",
- "php": "^8.1"
- },
- "conflict": {
- "laravel/framework": "10.40.0"
+ "laravel/prompts": "*",
+ "livewire/livewire": "^3.7|^4.0",
+ "php": "^8.2"
},
"require-dev": {
- "composer/composer": "^2.7.1",
- "laradumps/laradumps": "^3.1",
- "laradumps/laradumps-core": "^2.0",
- "larastan/larastan": "^2.9.0",
- "laravel/pint": "^1.14.0",
- "laravel/scout": "^10.9",
- "orchestra/testbench": "8.19|^9.0",
- "pestphp/pest": "^2.34.0"
+ "composer/composer": "^2.8",
+ "laradumps/laradumps": "^4.6",
+ "larastan/larastan": "^2.0|^3.0",
+ "laravel/pint": "^1.26",
+ "laravel/scout": "^10.11.3",
+ "openspout/openspout": "^4.24.5",
+ "orchestra/testbench": "^9.4|^10.0",
+ "pestphp/pest": "^3.0|^4.0"
},
"suggest": {
"openspout/openspout": "Required to export XLS and CSV"
@@ -4918,7 +4848,7 @@
"homepage": "https://github.com/power-components/livewire-powergrid",
"support": {
"issues": "https://github.com/Power-Components/livewire-powergrid/issues",
- "source": "https://github.com/Power-Components/livewire-powergrid/tree/v5.10.7"
+ "source": "https://github.com/Power-Components/livewire-powergrid/tree/v6.7.5"
},
"funding": [
{
@@ -4926,7 +4856,7 @@
"type": "github"
}
],
- "time": "2024-10-01T11:12:07+00:00"
+ "time": "2026-01-12T11:43:44+00:00"
},
{
"name": "psr/clock",
@@ -5342,16 +5272,16 @@
},
{
"name": "psy/psysh",
- "version": "v0.12.14",
+ "version": "v0.12.18",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
- "reference": "95c29b3756a23855a30566b745d218bee690bef2"
+ "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/bobthecow/psysh/zipball/95c29b3756a23855a30566b745d218bee690bef2",
- "reference": "95c29b3756a23855a30566b745d218bee690bef2",
+ "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ddff0ac01beddc251786fe70367cd8bbdb258196",
+ "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196",
"shasum": ""
},
"require": {
@@ -5359,8 +5289,8 @@
"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"
@@ -5415,9 +5345,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
- "source": "https://github.com/bobthecow/psysh/tree/v0.12.14"
+ "source": "https://github.com/bobthecow/psysh/tree/v0.12.18"
},
- "time": "2025-10-27T17:15:31+00:00"
+ "time": "2025-12-17T14:35:46+00:00"
},
{
"name": "pusher/pusher-php-server",
@@ -5602,29 +5532,30 @@
},
{
"name": "ralphjsmit/laravel-seo",
- "version": "1.7.2",
+ "version": "1.7.3",
"source": {
"type": "git",
"url": "https://github.com/ralphjsmit/laravel-seo.git",
- "reference": "55f72af14357b22665ed8428f46356f41a61c713"
+ "reference": "c020d92e4d31eb903c31a905ef258d4629bff75b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ralphjsmit/laravel-seo/zipball/55f72af14357b22665ed8428f46356f41a61c713",
- "reference": "55f72af14357b22665ed8428f46356f41a61c713",
+ "url": "https://api.github.com/repos/ralphjsmit/laravel-seo/zipball/c020d92e4d31eb903c31a905ef258d4629bff75b",
+ "reference": "c020d92e4d31eb903c31a905ef258d4629bff75b",
"shasum": ""
},
"require": {
- "illuminate/contracts": "^10.0|^11.0|^12.0",
- "php": "^8.0",
+ "illuminate/contracts": "^11.11|^12.0",
+ "php": "^8.2",
"ralphjsmit/laravel-helpers": "^1.10",
"spatie/laravel-package-tools": "^1.9.2"
},
"require-dev": {
"laravel/pint": "^1.16",
- "nesbot/carbon": "^2.66|^3.0",
- "nunomaduro/collision": "^7.0|^8.0|^9.0",
- "orchestra/testbench": "^9.0|^10.0",
+ "nesbot/carbon": "^3.0",
+ "nunomaduro/collision": "^8.0|^9.0",
+ "orchestra/testbench": "^9.16|^10.0",
+ "orchestra/testbench-core": "^9.1.4|^10.0",
"pestphp/pest": "^2.0|^3.0",
"pestphp/pest-plugin-laravel": "^2.0|^3.0",
"phpunit/phpunit": "^10.5|^11.5",
@@ -5671,9 +5602,9 @@
],
"support": {
"issues": "https://github.com/ralphjsmit/laravel-seo/issues",
- "source": "https://github.com/ralphjsmit/laravel-seo/tree/1.7.2"
+ "source": "https://github.com/ralphjsmit/laravel-seo/tree/1.7.3"
},
- "time": "2025-09-22T14:21:04+00:00"
+ "time": "2026-01-15T22:23:17+00:00"
},
{
"name": "ramsey/collection",
@@ -5753,20 +5684,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.9.1",
+ "version": "4.9.2",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
+ "reference": "8429c78ca35a09f27565311b98101e2826affde0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
- "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "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 || ^0.14",
+ "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"
},
@@ -5825,9 +5756,9 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.9.1"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.2"
},
- "time": "2025-09-04T20:59:21+00:00"
+ "time": "2025-12-14T04:43:48+00:00"
},
{
"name": "ratchet/rfc6455",
@@ -6420,16 +6351,16 @@
},
{
"name": "sentry/sentry",
- "version": "4.18.1",
+ "version": "4.19.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
- "reference": "04dcf20b39742b731b676f8b8d4f02d1db488af8"
+ "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/04dcf20b39742b731b676f8b8d4f02d1db488af8",
- "reference": "04dcf20b39742b731b676f8b8d4f02d1db488af8",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/1c21d60bebe67c0122335bd3fe977990435af0a3",
+ "reference": "1c21d60bebe67c0122335bd3fe977990435af0a3",
"shasum": ""
},
"require": {
@@ -6492,7 +6423,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
- "source": "https://github.com/getsentry/sentry-php/tree/4.18.1"
+ "source": "https://github.com/getsentry/sentry-php/tree/4.19.1"
},
"funding": [
{
@@ -6504,28 +6435,28 @@
"type": "custom"
}
],
- "time": "2025-11-11T09:34:53+00:00"
+ "time": "2025-12-02T15:57:41+00:00"
},
{
"name": "sentry/sentry-laravel",
- "version": "4.19.0",
+ "version": "4.20.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
- "reference": "7fdffd57e8fff0a6f9a18d9a83f32e960af63e3f"
+ "reference": "503853fa7ee74b34b64e76f1373db86cd11afe72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/7fdffd57e8fff0a6f9a18d9a83f32e960af63e3f",
- "reference": "7fdffd57e8fff0a6f9a18d9a83f32e960af63e3f",
+ "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.18.0",
- "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",
@@ -6582,7 +6513,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
- "source": "https://github.com/getsentry/sentry-laravel/tree/4.19.0"
+ "source": "https://github.com/getsentry/sentry-laravel/tree/4.20.1"
},
"funding": [
{
@@ -6594,7 +6525,7 @@
"type": "custom"
}
],
- "time": "2025-11-11T09:01:14+00:00"
+ "time": "2026-01-07T08:53:19+00:00"
},
{
"name": "simplesoftwareio/simple-qrcode",
@@ -6813,23 +6744,23 @@
},
{
"name": "spatie/commonmark-shiki-highlighter",
- "version": "2.5.1",
+ "version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/spatie/commonmark-shiki-highlighter.git",
- "reference": "595c7e0b45d4a63b17dfc1ccbd13532d431ec351"
+ "reference": "ef23368cff226658e9a348fd839b33ae6d95d2c6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/commonmark-shiki-highlighter/zipball/595c7e0b45d4a63b17dfc1ccbd13532d431ec351",
- "reference": "595c7e0b45d4a63b17dfc1ccbd13532d431ec351",
+ "url": "https://api.github.com/repos/spatie/commonmark-shiki-highlighter/zipball/ef23368cff226658e9a348fd839b33ae6d95d2c6",
+ "reference": "ef23368cff226658e9a348fd839b33ae6d95d2c6",
"shasum": ""
},
"require": {
"league/commonmark": "^2.4.2",
"php": "^8.0",
"spatie/shiki-php": "^2.2.2",
- "symfony/process": "^5.4|^6.4|^7.1"
+ "symfony/process": "^5.4|^6.4|^7.1|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.19|^v3.49.0",
@@ -6861,7 +6792,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/commonmark-shiki-highlighter/tree/2.5.1"
+ "source": "https://github.com/spatie/commonmark-shiki-highlighter/tree/2.5.2"
},
"funding": [
{
@@ -6869,25 +6800,25 @@
"type": "github"
}
],
- "time": "2025-01-13T11:25:47+00:00"
+ "time": "2025-11-24T15:27:35+00:00"
},
{
"name": "spatie/db-dumper",
- "version": "3.8.0",
+ "version": "3.8.3",
"source": {
"type": "git",
"url": "https://github.com/spatie/db-dumper.git",
- "reference": "91e1fd4dc000aefc9753cda2da37069fc996baee"
+ "reference": "eac3221fbe27fac51f388600d27b67b1b079406e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/db-dumper/zipball/91e1fd4dc000aefc9753cda2da37069fc996baee",
- "reference": "91e1fd4dc000aefc9753cda2da37069fc996baee",
+ "url": "https://api.github.com/repos/spatie/db-dumper/zipball/eac3221fbe27fac51f388600d27b67b1b079406e",
+ "reference": "eac3221fbe27fac51f388600d27b67b1b079406e",
"shasum": ""
},
"require": {
"php": "^8.0",
- "symfony/process": "^5.0|^6.0|^7.0"
+ "symfony/process": "^5.0|^6.0|^7.0|^8.0"
},
"require-dev": {
"pestphp/pest": "^1.22"
@@ -6920,7 +6851,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/db-dumper/tree/3.8.0"
+ "source": "https://github.com/spatie/db-dumper/tree/3.8.3"
},
"funding": [
{
@@ -6932,7 +6863,7 @@
"type": "github"
}
],
- "time": "2025-02-14T15:04:22+00:00"
+ "time": "2026-01-05T16:26:03+00:00"
},
{
"name": "spatie/eloquent-sortable",
@@ -7010,16 +6941,16 @@
},
{
"name": "spatie/image",
- "version": "3.8.6",
+ "version": "3.9.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/image.git",
- "reference": "0872c5968a7f044fe1e960c26433e54ceaede696"
+ "reference": "9a8e02839897b236f37708d24bcb12381ba050ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/image/zipball/0872c5968a7f044fe1e960c26433e54ceaede696",
- "reference": "0872c5968a7f044fe1e960c26433e54ceaede696",
+ "url": "https://api.github.com/repos/spatie/image/zipball/9a8e02839897b236f37708d24bcb12381ba050ff",
+ "reference": "9a8e02839897b236f37708d24bcb12381ba050ff",
"shasum": ""
},
"require": {
@@ -7029,18 +6960,18 @@
"php": "^8.2",
"spatie/image-optimizer": "^1.7.5",
"spatie/temporary-directory": "^2.2",
- "symfony/process": "^6.4|^7.0"
+ "symfony/process": "^6.4|^7.0|^8.0"
},
"require-dev": {
"ext-gd": "*",
"ext-imagick": "*",
"laravel/sail": "^1.34",
- "pestphp/pest": "^2.28",
+ "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"
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -7067,7 +6998,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/image/tree/3.8.6"
+ "source": "https://github.com/spatie/image/tree/3.9.1"
},
"funding": [
{
@@ -7079,32 +7010,32 @@
"type": "github"
}
],
- "time": "2025-09-25T12:06:17+00:00"
+ "time": "2026-01-12T07:34:13+00:00"
},
{
"name": "spatie/image-optimizer",
- "version": "1.8.0",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/image-optimizer.git",
- "reference": "4fd22035e81d98fffced65a8c20d9ec4daa9671c"
+ "reference": "2ad9ac7c19501739183359ae64ea6c15869c23d9"
},
"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": {
@@ -7132,9 +7063,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/laravel-backup",
@@ -7467,16 +7398,16 @@
},
{
"name": "spatie/laravel-medialibrary",
- "version": "11.17.5",
+ "version": "11.17.8",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-medialibrary.git",
- "reference": "eef29bbc701d786f2f6233ca4c40deb61282ac36"
+ "reference": "ce3edb8c163e159e41a945a24e4bf9ad7a7499c9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/eef29bbc701d786f2f6233ca4c40deb61282ac36",
- "reference": "eef29bbc701d786f2f6233ca4c40deb61282ac36",
+ "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/ce3edb8c163e159e41a945a24e4bf9ad7a7499c9",
+ "reference": "ce3edb8c163e159e41a945a24e4bf9ad7a7499c9",
"shasum": ""
},
"require": {
@@ -7509,8 +7440,8 @@
"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|^4.0",
+ "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",
@@ -7561,7 +7492,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-medialibrary/issues",
- "source": "https://github.com/spatie/laravel-medialibrary/tree/11.17.5"
+ "source": "https://github.com/spatie/laravel-medialibrary/tree/11.17.8"
},
"funding": [
{
@@ -7573,7 +7504,7 @@
"type": "github"
}
],
- "time": "2025-11-13T11:36:18+00:00"
+ "time": "2026-01-05T09:32:05+00:00"
},
{
"name": "spatie/laravel-package-tools",
@@ -7638,23 +7569,23 @@
},
{
"name": "spatie/laravel-signal-aware-command",
- "version": "2.1.0",
+ "version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-signal-aware-command.git",
- "reference": "8e8a226ed7fb45302294878ef339e75ffa9a878d"
+ "reference": "70207ba2702a9ee8f523af0cd4711d1104c5ca53"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-signal-aware-command/zipball/8e8a226ed7fb45302294878ef339e75ffa9a878d",
- "reference": "8e8a226ed7fb45302294878ef339e75ffa9a878d",
+ "url": "https://api.github.com/repos/spatie/laravel-signal-aware-command/zipball/70207ba2702a9ee8f523af0cd4711d1104c5ca53",
+ "reference": "70207ba2702a9ee8f523af0cd4711d1104c5ca53",
"shasum": ""
},
"require": {
"illuminate/contracts": "^11.0|^12.0",
"php": "^8.2",
"spatie/laravel-package-tools": "^1.4.3",
- "symfony/console": "^7.0"
+ "symfony/console": "^7.0|^8.0"
},
"require-dev": {
"brianium/paratest": "^6.2|^7.0",
@@ -7701,7 +7632,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-signal-aware-command/issues",
- "source": "https://github.com/spatie/laravel-signal-aware-command/tree/2.1.0"
+ "source": "https://github.com/spatie/laravel-signal-aware-command/tree/2.1.1"
},
"funding": [
{
@@ -7709,7 +7640,7 @@
"type": "github"
}
],
- "time": "2025-02-14T09:55:51+00:00"
+ "time": "2025-11-27T09:17:52+00:00"
},
{
"name": "spatie/laravel-sluggable",
@@ -7842,29 +7773,29 @@
},
{
"name": "spatie/laravel-translatable",
- "version": "6.11.4",
+ "version": "6.12.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-translatable.git",
- "reference": "032d85b28de315310dab2048b857016f1194f68b"
+ "reference": "8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/032d85b28de315310dab2048b857016f1194f68b",
- "reference": "032d85b28de315310dab2048b857016f1194f68b",
+ "url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349",
+ "reference": "8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349",
"shasum": ""
},
"require": {
- "illuminate/database": "^10.0|^11.0|^12.0",
- "illuminate/support": "^10.0|^11.0|^12.0",
- "php": "^8.0",
- "spatie/laravel-package-tools": "^1.11"
+ "illuminate/database": "^11.0|^12.0",
+ "illuminate/support": "^11.0|^12.0",
+ "php": "^8.3",
+ "spatie/laravel-package-tools": "^1.92.7"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.64",
- "mockery/mockery": "^1.4",
- "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0",
- "pestphp/pest": "^1.20|^2.0|^3.0"
+ "friendsofphp/php-cs-fixer": "^3.90",
+ "mockery/mockery": "^1.6.12",
+ "orchestra/testbench": "^9.0|^10.0",
+ "pestphp/pest": "^4.0.0"
},
"type": "library",
"extra": {
@@ -7913,7 +7844,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-translatable/issues",
- "source": "https://github.com/spatie/laravel-translatable/tree/6.11.4"
+ "source": "https://github.com/spatie/laravel-translatable/tree/6.12.0"
},
"funding": [
{
@@ -7921,7 +7852,7 @@
"type": "github"
}
],
- "time": "2025-02-20T15:51:22+00:00"
+ "time": "2025-11-24T15:57:48+00:00"
},
{
"name": "spatie/shiki-php",
@@ -7990,16 +7921,16 @@
},
{
"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": {
@@ -8035,7 +7966,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": [
{
@@ -8047,7 +7978,7 @@
"type": "github"
}
],
- "time": "2025-01-13T13:04:43+00:00"
+ "time": "2026-01-12T07:42:22+00:00"
},
{
"name": "staudenmeir/eloquent-has-many-deep",
@@ -8159,25 +8090,25 @@
},
{
"name": "swentel/nostr-php",
- "version": "1.9.2",
+ "version": "1.9.3",
"source": {
"type": "git",
"url": "https://github.com/nostrver-se/nostr-php.git",
- "reference": "8fb8337354b2e9d48a901276c7814d7fa7b25653"
+ "reference": "c415dd1bf20c1b414eca94005288cc137a79e0d7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nostrver-se/nostr-php/zipball/8fb8337354b2e9d48a901276c7814d7fa7b25653",
- "reference": "8fb8337354b2e9d48a901276c7814d7fa7b25653",
+ "url": "https://api.github.com/repos/nostrver-se/nostr-php/zipball/c415dd1bf20c1b414eca94005288cc137a79e0d7",
+ "reference": "c415dd1bf20c1b414eca94005288cc137a79e0d7",
"shasum": ""
},
"require": {
"bitwasp/bech32": "^0.0.1",
+ "dsbaars/chacha20": "^0.3.0",
"ext-gmp": "*",
"ext-xml": "*",
- "leigh/chacha20": "^0.2.0",
"paragonie/ecc": "^2.4",
- "php": ">=8.1 <8.5",
+ "php": ">=8.2 <8.6",
"phrity/websocket": "^3.0",
"simplito/elliptic-php": "^1.0"
},
@@ -8218,22 +8149,22 @@
"chat": "https://t.me/nostr_php",
"issue": "https://github.com/swentel/nostr-php/issues",
"issues": "https://github.com/nostrver-se/nostr-php/issues",
- "source": "https://github.com/nostrver-se/nostr-php/tree/1.9.2"
+ "source": "https://github.com/nostrver-se/nostr-php/tree/1.9.3"
},
- "time": "2025-06-04T14:51:06+00:00"
+ "time": "2025-12-04T09:09:22+00:00"
},
{
"name": "symfony/clock",
- "version": "v7.3.0",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/clock.git",
- "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24"
+ "reference": "9169f24776edde469914c1e7a1442a50f7a4e110"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
- "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110",
+ "reference": "9169f24776edde469914c1e7a1442a50f7a4e110",
"shasum": ""
},
"require": {
@@ -8278,7 +8209,7 @@
"time"
],
"support": {
- "source": "https://github.com/symfony/clock/tree/v7.3.0"
+ "source": "https://github.com/symfony/clock/tree/v7.4.0"
},
"funding": [
{
@@ -8289,25 +8220,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:39:26+00:00"
},
{
"name": "symfony/console",
- "version": "v7.3.6",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a"
+ "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
- "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
+ "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
+ "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
"shasum": ""
},
"require": {
@@ -8315,7 +8250,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",
@@ -8329,16 +8264,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": {
@@ -8372,7 +8307,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.3.6"
+ "source": "https://github.com/symfony/console/tree/v7.4.3"
},
"funding": [
{
@@ -8392,20 +8327,20 @@
"type": "tidelift"
}
],
- "time": "2025-11-04T01:21:42+00:00"
+ "time": "2025-12-23T14:50:43+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v7.3.6",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "84321188c4754e64273b46b406081ad9b18e8614"
+ "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/84321188c4754e64273b46b406081ad9b18e8614",
- "reference": "84321188c4754e64273b46b406081ad9b18e8614",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135",
+ "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135",
"shasum": ""
},
"require": {
@@ -8441,7 +8376,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v7.3.6"
+ "source": "https://github.com/symfony/css-selector/tree/v7.4.0"
},
"funding": [
{
@@ -8461,7 +8396,7 @@
"type": "tidelift"
}
],
- "time": "2025-10-29T17:24:25+00:00"
+ "time": "2025-10-30T13:39:42+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -8532,32 +8467,33 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.3.6",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "bbe40bfab84323d99dab491b716ff142410a92a8"
+ "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/bbe40bfab84323d99dab491b716ff142410a92a8",
- "reference": "bbe40bfab84323d99dab491b716ff142410a92a8",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2",
+ "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2",
"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": [
@@ -8589,7 +8525,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.6"
+ "source": "https://github.com/symfony/error-handler/tree/v7.4.0"
},
"funding": [
{
@@ -8609,20 +8545,20 @@
"type": "tidelift"
}
],
- "time": "2025-10-31T19:12:50+00:00"
+ "time": "2025-11-05T14:29:59+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.3.3",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191"
+ "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191",
- "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d",
+ "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d",
"shasum": ""
},
"require": {
@@ -8639,13 +8575,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": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/error-handler": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/framework-bundle": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^6.4|^7.0"
+ "symfony/stopwatch": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -8673,7 +8610,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.3"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.0"
},
"funding": [
{
@@ -8693,7 +8630,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-13T11:49:31+00:00"
+ "time": "2025-10-28T09:38:46+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -8773,23 +8710,23 @@
},
{
"name": "symfony/finder",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "9f696d2f1e340484b4683f7853b273abff94421f"
+ "reference": "fffe05569336549b20a1be64250b40516d6e8d06"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f",
- "reference": "9f696d2f1e340484b4683f7853b273abff94421f",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06",
+ "reference": "fffe05569336549b20a1be64250b40516d6e8d06",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
"require-dev": {
- "symfony/filesystem": "^6.4|^7.0"
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -8817,7 +8754,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.5"
+ "source": "https://github.com/symfony/finder/tree/v7.4.3"
},
"funding": [
{
@@ -8837,27 +8774,26 @@
"type": "tidelift"
}
],
- "time": "2025-10-15T18:45:57+00:00"
+ "time": "2025-12-23T14:50:43+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v7.3.7",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4"
+ "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4",
- "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52",
+ "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52",
"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",
@@ -8866,13 +8802,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": {
@@ -8900,7 +8836,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.7"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.4.3"
},
"funding": [
{
@@ -8920,29 +8856,29 @@
"type": "tidelift"
}
],
- "time": "2025-11-08T16:41:12+00:00"
+ "time": "2025-12-23T14:23:49+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.3.7",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce"
+ "reference": "885211d4bed3f857b8c964011923528a55702aa5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b8e9b748ea95fa4539c208e2487c435d3c87ce",
- "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5",
+ "reference": "885211d4bed3f857b8c964011923528a55702aa5",
"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": {
@@ -8952,6 +8888,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",
@@ -8969,27 +8906,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",
@@ -9018,7 +8955,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.7"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.4.3"
},
"funding": [
{
@@ -9038,20 +8975,20 @@
"type": "tidelift"
}
],
- "time": "2025-11-12T11:38:40+00:00"
+ "time": "2025-12-31T08:43:57+00:00"
},
{
"name": "symfony/mailer",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba"
+ "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/fd497c45ba9c10c37864e19466b090dcb60a50ba",
- "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/e472d35e230108231ccb7f51eb6b2100cac02ee4",
+ "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4",
"shasum": ""
},
"require": {
@@ -9059,8 +8996,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": {
@@ -9071,10 +9008,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": {
@@ -9102,7 +9039,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v7.3.5"
+ "source": "https://github.com/symfony/mailer/tree/v7.4.3"
},
"funding": [
{
@@ -9122,24 +9059,25 @@
"type": "tidelift"
}
],
- "time": "2025-10-24T14:27:20+00:00"
+ "time": "2025-12-16T08:02:06+00:00"
},
{
"name": "symfony/mime",
- "version": "v7.3.4",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35"
+ "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/b1b828f69cbaf887fa835a091869e55df91d0e35",
- "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a",
+ "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
@@ -9154,11 +9092,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": {
@@ -9190,7 +9128,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.3.4"
+ "source": "https://github.com/symfony/mime/tree/v7.4.0"
},
"funding": [
{
@@ -9210,20 +9148,20 @@
"type": "tidelift"
}
],
- "time": "2025-09-16T08:38:17+00:00"
+ "time": "2025-11-16T10:14:42+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v7.3.3",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d"
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
- "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80",
"shasum": ""
},
"require": {
@@ -9261,7 +9199,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.3.3"
+ "source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
},
"funding": [
{
@@ -9281,7 +9219,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-05T10:16:07+00:00"
+ "time": "2025-11-12T15:39:26+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -9869,6 +9807,86 @@
],
"time": "2025-07-08T02:45:35+00:00"
},
+ {
+ "name": "symfony/polyfill-php85",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php85.git",
+ "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+ "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php85\\": ""
+ },
+ "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 backporting some PHP 8.5+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php85/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": "2025-06-23T16:12:55+00:00"
+ },
{
"name": "symfony/polyfill-uuid",
"version": "v1.33.0",
@@ -9954,16 +9972,16 @@
},
{
"name": "symfony/process",
- "version": "v7.3.4",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b"
+ "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b",
- "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b",
+ "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
+ "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
"shasum": ""
},
"require": {
@@ -9995,7 +10013,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.3.4"
+ "source": "https://github.com/symfony/process/tree/v7.4.3"
},
"funding": [
{
@@ -10015,26 +10033,26 @@
"type": "tidelift"
}
],
- "time": "2025-09-11T10:12:26+00:00"
+ "time": "2025-12-19T10:00:43+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
- "version": "v7.3.0",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git",
- "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f"
+ "reference": "0101ff8bd0506703b045b1670960302d302a726c"
},
"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/0101ff8bd0506703b045b1670960302d302a726c",
+ "reference": "0101ff8bd0506703b045b1670960302d302a726c",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/http-message": "^1.0|^2.0",
- "symfony/http-foundation": "^6.4|^7.0"
+ "symfony/http-foundation": "^6.4|^7.0|^8.0"
},
"conflict": {
"php-http/discovery": "<1.15",
@@ -10044,11 +10062,12 @@
"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": "^6.4|^7.0|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0",
+ "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0",
+ "symfony/runtime": "^6.4.13|^7.1.6|^8.0"
},
"type": "symfony-bridge",
"autoload": {
@@ -10082,7 +10101,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/v7.4.0"
},
"funding": [
{
@@ -10093,25 +10112,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": "2025-11-13T08:38:49+00:00"
},
{
"name": "symfony/routing",
- "version": "v7.3.6",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091"
+ "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/c97abe725f2a1a858deca629a6488c8fc20c3091",
- "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
+ "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
"shasum": ""
},
"require": {
@@ -10125,11 +10148,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": {
@@ -10163,7 +10186,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.3.6"
+ "source": "https://github.com/symfony/routing/tree/v7.4.3"
},
"funding": [
{
@@ -10183,7 +10206,7 @@
"type": "tidelift"
}
],
- "time": "2025-11-05T07:57:47+00:00"
+ "time": "2025-12-19T10:00:43+00:00"
},
{
"name": "symfony/service-contracts",
@@ -10274,22 +10297,23 @@
},
{
"name": "symfony/string",
- "version": "v7.3.4",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "f96476035142921000338bad71e5247fbc138872"
+ "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872",
- "reference": "f96476035142921000338bad71e5247fbc138872",
+ "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003",
+ "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3.0",
"symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-grapheme": "~1.33",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
@@ -10297,11 +10321,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/emoji": "^7.1",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
+ "symfony/emoji": "^7.1|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -10340,7 +10364,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.3.4"
+ "source": "https://github.com/symfony/string/tree/v7.4.0"
},
"funding": [
{
@@ -10360,27 +10384,27 @@
"type": "tidelift"
}
],
- "time": "2025-09-11T14:36:48+00:00"
+ "time": "2025-11-27T13:27:24+00:00"
},
{
"name": "symfony/translation",
- "version": "v7.3.4",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "ec25870502d0c7072d086e8ffba1420c85965174"
+ "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/ec25870502d0c7072d086e8ffba1420c85965174",
- "reference": "ec25870502d0c7072d086e8ffba1420c85965174",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/7ef27c65d78886f7599fdd5c93d12c9243ecf44d",
+ "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
- "symfony/translation-contracts": "^2.5|^3.0"
+ "symfony/translation-contracts": "^2.5.3|^3.3"
},
"conflict": {
"nikic/php-parser": "<5.0",
@@ -10399,17 +10423,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": "^6.4|^7.0|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^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": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -10440,7 +10464,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.3.4"
+ "source": "https://github.com/symfony/translation/tree/v7.4.3"
},
"funding": [
{
@@ -10460,7 +10484,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-07T11:39:36+00:00"
+ "time": "2025-12-29T09:31:36+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -10546,16 +10570,16 @@
},
{
"name": "symfony/uid",
- "version": "v7.3.1",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
- "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb"
+ "reference": "2498e9f81b7baa206f44de583f2f48350b90142c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb",
- "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c",
+ "reference": "2498e9f81b7baa206f44de583f2f48350b90142c",
"shasum": ""
},
"require": {
@@ -10563,7 +10587,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": {
@@ -10600,7 +10624,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v7.3.1"
+ "source": "https://github.com/symfony/uid/tree/v7.4.0"
},
"funding": [
{
@@ -10611,25 +10635,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": "2025-09-25T11:02:55+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d"
+ "reference": "7e99bebcb3f90d8721890f2963463280848cba92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
- "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92",
+ "reference": "7e99bebcb3f90d8721890f2963463280848cba92",
"shasum": ""
},
"require": {
@@ -10641,10 +10669,10 @@
"symfony/console": "<6.4"
},
"require-dev": {
- "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": [
@@ -10683,7 +10711,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.3.5"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.4.3"
},
"funding": [
{
@@ -10703,32 +10731,32 @@
"type": "tidelift"
}
],
- "time": "2025-09-27T09:00:46+00:00"
+ "time": "2025-12-18T07:04:31+00:00"
},
{
"name": "symfony/yaml",
- "version": "v7.3.5",
+ "version": "v7.4.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc"
+ "reference": "24dd4de28d2e3988b311751ac49e684d783e2345"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/90208e2fc6f68f613eae7ca25a2458a931b1bacc",
- "reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc",
+ "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"
@@ -10759,7 +10787,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v7.3.5"
+ "source": "https://github.com/symfony/yaml/tree/v7.4.1"
},
"funding": [
{
@@ -10779,27 +10807,27 @@
"type": "tidelift"
}
],
- "time": "2025-09-27T09:00:46+00:00"
+ "time": "2025-12-04T18:11:45+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",
@@ -10832,32 +10860,32 @@
"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": "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",
@@ -10906,7 +10934,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": [
{
@@ -10918,7 +10946,7 @@
"type": "tidelift"
}
],
- "time": "2025-04-30T23:37:27+00:00"
+ "time": "2025-12-27T19:49:13+00:00"
},
{
"name": "voku/portable-ascii",
@@ -11513,17 +11541,282 @@
"time": "2025-04-30T06:54:44+00:00"
},
{
- "name": "laravel/pint",
- "version": "v1.25.1",
+ "name": "illuminate/json-schema",
+ "version": "v12.47.0",
"source": {
"type": "git",
- "url": "https://github.com/laravel/pint.git",
- "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9"
+ "url": "https://github.com/illuminate/json-schema.git",
+ "reference": "d161f398dab36f08cf131997362bc2e3ecb0309a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9",
- "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9",
+ "url": "https://api.github.com/repos/illuminate/json-schema/zipball/d161f398dab36f08cf131997362bc2e3ecb0309a",
+ "reference": "d161f398dab36f08cf131997362bc2e3ecb0309a",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/contracts": "^10.50.0|^11.47.0|^12.40.2",
+ "php": "^8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "12.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Illuminate\\JsonSchema\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "The Illuminate Json Schema package.",
+ "homepage": "https://laravel.com",
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "time": "2025-11-28T18:45:48+00:00"
+ },
+ {
+ "name": "laravel/boost",
+ "version": "v1.8.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/boost.git",
+ "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/boost/zipball/aad8b2a423b0a886c2ce7ee92abbfde69992ff32",
+ "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^7.9",
+ "illuminate/console": "^10.49.0|^11.45.3|^12.41.1",
+ "illuminate/contracts": "^10.49.0|^11.45.3|^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",
+ "laravel/mcp": "^0.5.1",
+ "laravel/prompts": "0.1.25|^0.3.6",
+ "laravel/roster": "^0.2.9",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "laravel/pint": "^1.20.0",
+ "mockery/mockery": "^1.6.12",
+ "orchestra/testbench": "^8.36.0|^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-14T14:51:16+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/pail",
+ "version": "v1.2.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pail.git",
+ "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pail/zipball/49f92285ff5d6fc09816e976a004f8dec6a0ea30",
+ "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "illuminate/console": "^10.24|^11.0|^12.0",
+ "illuminate/contracts": "^10.24|^11.0|^12.0",
+ "illuminate/log": "^10.24|^11.0|^12.0",
+ "illuminate/process": "^10.24|^11.0|^12.0",
+ "illuminate/support": "^10.24|^11.0|^12.0",
+ "nunomaduro/termwind": "^1.15|^2.0",
+ "php": "^8.2",
+ "symfony/console": "^6.0|^7.0"
+ },
+ "require-dev": {
+ "laravel/framework": "^10.24|^11.0|^12.0",
+ "laravel/pint": "^1.13",
+ "orchestra/testbench-core": "^8.13|^9.17|^10.8",
+ "pestphp/pest": "^2.20|^3.0|^4.0",
+ "pestphp/pest-plugin-type-coverage": "^2.3|^3.0|^4.0",
+ "phpstan/phpstan": "^1.12.27",
+ "symfony/var-dumper": "^6.3|^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Laravel\\Pail\\PailServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Pail\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ },
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Easily delve into your Laravel application's log files directly from the command line.",
+ "homepage": "https://github.com/laravel/pail",
+ "keywords": [
+ "dev",
+ "laravel",
+ "logs",
+ "php",
+ "tail"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pail/issues",
+ "source": "https://github.com/laravel/pail"
+ },
+ "time": "2025-11-20T16:29:35+00:00"
+ },
+ {
+ "name": "laravel/pint",
+ "version": "v1.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pint.git",
+ "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/c67b4195b75491e4dfc6b00b1c78b68d86f54c90",
+ "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90",
"shasum": ""
},
"require": {
@@ -11534,13 +11827,13 @@
"php": "^8.2.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.87.2",
- "illuminate/view": "^11.46.0",
- "larastan/larastan": "^3.7.1",
- "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"
@@ -11566,6 +11859,7 @@
"description": "An opinionated code formatter for PHP.",
"homepage": "https://laravel.com",
"keywords": [
+ "dev",
"format",
"formatter",
"lint",
@@ -11576,7 +11870,68 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2025-09-19T02:57:12+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": "mockery/mockery",
@@ -12315,16 +12670,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "5.6.4",
+ "version": "5.6.6",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2"
+ "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90a04bcbf03784066f16038e87e23a0a83cee3c2",
- "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8",
+ "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8",
"shasum": ""
},
"require": {
@@ -12334,7 +12689,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",
@@ -12373,22 +12728,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.4"
+ "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6"
},
- "time": "2025-11-17T21:13:10+00:00"
+ "time": "2025-12-22T21:13:58+00:00"
},
{
"name": "phpdocumentor/type-resolver",
- "version": "1.11.0",
+ "version": "1.12.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "8cbe6100e8971efbf8e2e7da3a202ba83eafd5a3"
+ "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/8cbe6100e8971efbf8e2e7da3a202ba83eafd5a3",
- "reference": "8cbe6100e8971efbf8e2e7da3a202ba83eafd5a3",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195",
+ "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195",
"shasum": ""
},
"require": {
@@ -12431,22 +12786,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.11.0"
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0"
},
- "time": "2025-11-19T20:28:58+00:00"
+ "time": "2025-11-21T15:09:14+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "2.3.0",
+ "version": "2.3.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495"
+ "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495",
- "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374",
+ "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374",
"shasum": ""
},
"require": {
@@ -12478,9 +12833,9 @@
"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.0"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1"
},
- "time": "2025-08-30T15:50:23+00:00"
+ "time": "2026-01-12T11:33:04+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -13968,23 +14323,23 @@
},
{
"name": "webmozart/assert",
- "version": "1.12.1",
+ "version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
- "reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
+ "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
- "reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/ce6a2f100c404b2d32a1dd1270f9b59ad4f57649",
+ "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
- "php": "^7.2 || ^8.0"
+ "php": "^8.2"
},
"suggest": {
"ext-intl": "",
@@ -13994,7 +14349,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.10-dev"
+ "dev-feature/2-0": "2.0-dev"
}
},
"autoload": {
@@ -14010,6 +14365,10 @@
{
"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.",
@@ -14020,9 +14379,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.12.1"
+ "source": "https://github.com/webmozarts/assert/tree/2.1.2"
},
- "time": "2025-10-29T15:56:20+00:00"
+ "time": "2026-01-13T14:02:24+00:00"
}
],
"aliases": [],
@@ -14034,5 +14393,5 @@
"php": "^8.2"
},
"platform-dev": {},
- "plugin-api-version": "2.6.0"
+ "plugin-api-version": "2.9.0"
}
diff --git a/config/livewire.php b/config/livewire.php
new file mode 100644
index 0000000..2690e9b
--- /dev/null
+++ b/config/livewire.php
@@ -0,0 +1,282 @@
+ [
+ resource_path('views/livewire'),
+ resource_path('views/components'),
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Component Namespaces
+ |---------------------------------------------------------------------------
+ |
+ | This value sets default namespaces that will be used to resolve view-based
+ | components like single-file and multi-file components. These folders'll
+ | also be referenced when creating new components via the make command.
+ |
+ */
+
+ 'component_namespaces' => [
+ 'layouts' => resource_path('views/layouts'),
+ 'pages' => resource_path('views/pages'),
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Page Layout
+ |---------------------------------------------------------------------------
+ | The view that will be used as the layout when rendering a single component as
+ | an entire page via `Route::livewire('/post/create', 'pages::create-post')`.
+ | In this case, the content of pages::create-post will render into $slot.
+ |
+ */
+
+ 'component_layout' => 'layouts::app',
+
+ /*
+ |---------------------------------------------------------------------------
+ | Lazy Loading Placeholder
+ |---------------------------------------------------------------------------
+ | Livewire allows you to lazy load components that would otherwise slow down
+ | the initial page load. Every component can have a custom placeholder or
+ | you can define the default placeholder view for all components below.
+ |
+ */
+
+ 'component_placeholder' => null, // Example: 'placeholders::skeleton'
+
+ /*
+ |---------------------------------------------------------------------------
+ | Make Command
+ |---------------------------------------------------------------------------
+ | This value determines the default configuration for the artisan make command
+ | You can configure the component type (sfc, mfc, class) and whether to use
+ | the high-voltage (⚡) emoji as a prefix in the sfc|mfc component names.
+ |
+ */
+
+ 'make_command' => [
+ 'type' => 'sfc', // Options: 'sfc', 'mfc', 'class'
+ 'emoji' => true, // Options: true, false
+ 'with' => [
+ 'js' => false,
+ 'css' => false,
+ 'test' => false,
+ ],
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Class Namespace
+ |---------------------------------------------------------------------------
+ |
+ | This value sets the root class namespace for Livewire component classes in
+ | your application. This value will change where component auto-discovery
+ | finds components. It's also referenced by the file creation commands.
+ |
+ */
+
+ 'class_namespace' => 'App\\Livewire',
+
+ /*
+ |---------------------------------------------------------------------------
+ | Class Path
+ |---------------------------------------------------------------------------
+ |
+ | This value is used to specify the path where Livewire component class files
+ | are created when running creation commands like `artisan make:livewire`.
+ | This path is customizable to match your projects directory structure.
+ |
+ */
+
+ 'class_path' => app_path('Livewire'),
+
+ /*
+ |---------------------------------------------------------------------------
+ | View Path
+ |---------------------------------------------------------------------------
+ |
+ | This value is used to specify where Livewire component Blade templates are
+ | stored when running file creation commands like `artisan make:livewire`.
+ | It is also used if you choose to omit a component's render() method.
+ |
+ */
+
+ 'view_path' => resource_path('views/livewire'),
+
+ /*
+ |---------------------------------------------------------------------------
+ | Temporary File Uploads
+ |---------------------------------------------------------------------------
+ |
+ | Livewire handles file uploads by storing uploads in a temporary directory
+ | before the file is stored permanently. All file uploads are directed to
+ | a global endpoint for temporary storage. You may configure this below:
+ |
+ */
+
+ 'temporary_file_upload' => [
+ 'disk' => env('LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK'), // Example: 'local', 's3' | Default: 'default'
+ 'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB)
+ 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp'
+ 'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1'
+ 'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs...
+ 'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
+ 'mov', 'avi', 'wmv', 'mp3', 'm4a',
+ 'jpg', 'jpeg', 'mpga', 'webp', 'wma',
+ ],
+ 'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated...
+ 'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs...
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Render On Redirect
+ |---------------------------------------------------------------------------
+ |
+ | This value determines if Livewire will run a component's `render()` method
+ | after a redirect has been triggered using something like `redirect(...)`
+ | Setting this to true will render the view once more before redirecting
+ |
+ */
+
+ 'render_on_redirect' => false,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Eloquent Model Binding
+ |---------------------------------------------------------------------------
+ |
+ | Previous versions of Livewire supported binding directly to eloquent model
+ | properties using wire:model by default. However, this behavior has been
+ | deemed too "magical" and has therefore been put under a feature flag.
+ |
+ */
+
+ 'legacy_model_binding' => false,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Auto-inject Frontend Assets
+ |---------------------------------------------------------------------------
+ |
+ | By default, Livewire automatically injects its JavaScript and CSS into the
+ |
and of pages containing Livewire components. By disabling
+ | this behavior, you need to use @livewireStyles and @livewireScripts.
+ |
+ */
+
+ 'inject_assets' => true,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Navigate (SPA mode)
+ |---------------------------------------------------------------------------
+ |
+ | By adding `wire:navigate` to links in your Livewire application, Livewire
+ | will prevent the default link handling and instead request those pages
+ | via AJAX, creating an SPA-like effect. Configure this behavior here.
+ |
+ */
+
+ 'navigate' => [
+ 'show_progress_bar' => true,
+ 'progress_bar_color' => '#2299dd',
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | HTML Morph Markers
+ |---------------------------------------------------------------------------
+ |
+ | Livewire intelligently "morphs" existing HTML into the newly rendered HTML
+ | after each update. To make this process more reliable, Livewire injects
+ | "markers" into the rendered Blade surrounding @if, @class & @foreach.
+ |
+ */
+
+ 'inject_morph_markers' => true,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Smart Wire Keys
+ |---------------------------------------------------------------------------
+ |
+ | Livewire uses loops and keys used within loops to generate smart keys that
+ | are applied to nested components that don't have them. This makes using
+ | nested components more reliable by ensuring that they all have keys.
+ |
+ */
+
+ 'smart_wire_keys' => true,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Pagination Theme
+ |---------------------------------------------------------------------------
+ |
+ | When enabling Livewire's pagination feature by using the `WithPagination`
+ | trait, Livewire will use Tailwind templates to render pagination views
+ | on the page. If you want Bootstrap CSS, you can specify: "bootstrap"
+ |
+ */
+
+ 'pagination_theme' => 'tailwind',
+
+ /*
+ |---------------------------------------------------------------------------
+ | Release Token
+ |---------------------------------------------------------------------------
+ |
+ | This token is stored client-side and sent along with each request to check
+ | a users session to see if a new release has invalidated it. If there is
+ | a mismatch it will throw an error and prompt for a browser refresh.
+ |
+ */
+
+ 'release_token' => 'a',
+
+ /*
+ |---------------------------------------------------------------------------
+ | CSP Safe
+ |---------------------------------------------------------------------------
+ |
+ | This config is used to determine if Livewire will use the CSP-safe version
+ | of Alpine in its bundle. This is useful for applications that are using
+ | strict Content Security Policy (CSP) to protect against XSS attacks.
+ |
+ */
+
+ 'csp_safe' => false,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Payload Guards
+ |---------------------------------------------------------------------------
+ |
+ | These settings protect against malicious or oversized payloads that could
+ | cause denial of service. The default values should feel reasonable for
+ | most web applications. Each can be set to null to disable the limit.
+ |
+ */
+
+ 'payload' => [
+ 'max_size' => 1024 * 1024, // 1MB - maximum request payload size in bytes
+ 'max_nesting_depth' => 10, // Maximum depth of dot-notation property paths
+ 'max_calls' => 50, // Maximum method calls per request
+ 'max_components' => 20, // Maximum components per batch request
+ ],
+];
diff --git a/opencode.json b/opencode.json
new file mode 100644
index 0000000..6f800ed
--- /dev/null
+++ b/opencode.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://opencode.ai/config.json",
+ "mcp": {
+ "laravel-boost": {
+ "type": "local",
+ "enabled": true,
+ "command": [
+ "vendor/bin/sail",
+ "artisan",
+ "boost:mcp"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
new file mode 100644
index 0000000..f884b3d
--- /dev/null
+++ b/resources/views/layouts/app.blade.php
@@ -0,0 +1,197 @@
+
+
+
+
+
+ {!! seo($seo ?? null) !!}
+
+ {{ $title ?? 'Page Title' }}
+ @livewireStyles
+ @wireUiScripts
+ @stack('scripts')
+ @vite(['resources/js/app.js','resources/css/app.css'])
+ @googlefonts
+
+
+
+ @include('components.layouts.partials.styles')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open sidebar
+
+
+
+
+
+
+
+
+
+
+
+
+ {{--@include('components.layouts.partials.search-button')--}}
+
+ {{--@include('components.layouts.partials.notification-buttons')--}}
+
+
+ @if(\App\Support\NostrAuth::check())
+
+ @else
+
+ @endif
+
+
+
+
+ {{--@include('components.layouts.partials.dark-mode-toggle')--}}
+
+
+ {{--
--}}
+
+ {{--@include('components.layouts.partials.user-button')--}}
+
+
+
+
+
+
+
+ {{ $slot }}
+
+
+
+@livewireScriptConfig
+
+
+
+
diff --git a/resources/views/livewire/association/election/admin.blade.php b/resources/views/livewire/association/election/admin.blade.php
new file mode 100644
index 0000000..b3d1411
--- /dev/null
+++ b/resources/views/livewire/association/election/admin.blade.php
@@ -0,0 +1,74 @@
+
+ ['icon' => 'fa-crown', 'title' => 'Präsidium'],
+ 'board' => ['icon' => 'fa-users', 'title' => 'Vorstandsmitglieder'],
+ ];
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+ Wahl des Vorstands year); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Mitglieder
+
+ Du bist nicht berechtigt, Mitglieder zu bearbeiten.
+
+
+
+
+
+
diff --git a/resources/views/livewire/association/election/index.blade.php b/resources/views/livewire/association/election/index.blade.php
new file mode 100644
index 0000000..f1e0f03
--- /dev/null
+++ b/resources/views/livewire/association/election/index.blade.php
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
Einstellungen
+
+ Du bist nicht berechtigt, die Einstellungen zu bearbeiten.
+
+
+
+
+
+
+
diff --git a/resources/views/pages/association/election/[Election:year].blade.php b/resources/views/livewire/association/election/show.blade.php
similarity index 80%
rename from resources/views/pages/association/election/[Election:year].blade.php
rename to resources/views/livewire/association/election/show.blade.php
index 35ba73b..7f0f33d 100644
--- a/resources/views/pages/association/election/[Election:year].blade.php
+++ b/resources/views/livewire/association/election/show.blade.php
@@ -1,177 +1,12 @@
- false,
- 'showLog' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
- 'events' => [],
- 'boardEvents' => [],
- 'election' => fn() => $election,
- 'plebs' => [],
- 'search' => '',
- 'signThisEvent' => '',
- 'isNotClosed' => true,
-]);
-
-mount(function () {
- $this->plebs = \App\Models\EinundzwanzigPleb::query()
- ->with(['profile'])
- ->whereIn('association_status', [3, 4])
- ->orderBy('association_status', 'desc')
- ->get()
- ->toArray();
- $this->loadEvents();
- $this->loadBoardEvents();
- if ($this->election->end_time?->isPast() || !config('services.voting')) {
- $this->isNotClosed = false;
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- $logPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- ];
- if (in_array($this->currentPubkey, $logPubkeys, true)) {
- $this->showLog = true;
- $this->isAllowed = true;
- }
- },
- 'echo:votes,.newVote' => function () {
- $this->loadEvents();
- $this->loadBoardEvents();
- },
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-updated([
- 'search' => function ($value) {
- $this->plebs = \App\Models\EinundzwanzigPleb::query()
- ->with(['profile'])
- ->whereIn('association_status', [3, 4])
- ->where(fn($query)
- => $query
- ->where('pubkey', 'like', "%$value%")
- ->orWhereHas('profile', fn($query) => $query->where('name', 'ilike', "%$value%")))
- ->orderBy('association_status', 'desc')
- ->get()
- ->toArray();
- },
-]);
-
-$loadEvents = function () {
- $this->events = $this->loadNostrEvents([32122]);
-};
-
-$loadBoardEvents = function () {
- $this->boardEvents = $this->loadNostrEvents([2121]);
-};
-
-$loadNostrEvents = function ($kinds) {
- $subscription = new Subscription();
- $subscriptionId = $subscription->setId();
- $filter = new Filter();
- $filter->setKinds($kinds);
- $requestMessage = new RequestMessage($subscriptionId, [$filter]);
- $relaySet = new RelaySet();
- $relaySet->setRelays([new Relay(config('services.relay'))]);
- $request = new Request($relaySet, $requestMessage);
- $response = $request->send();
- return collect($response[config('services.relay')])
- ->map(function($event) {
- if(!isset($event->event)) {
- return false;
- }
- return [
- 'id' => $event->event->id,
- 'kind' => $event->event->kind,
- 'content' => $event->event->content,
- 'pubkey' => $event->event->pubkey,
- 'tags' => $event->event->tags,
- 'created_at' => $event->event->created_at,
- ];
- })
- ->filter()
- ->toArray();
-};
-
-$vote = function ($pubkey, $type, $board = false) {
- if ($this->election->end_time?->isPast()) {
- $this->isNotClosed = false;
- return;
- }
- $note = new NostrEvent();
- $note->setKind($board ? 2121 : 32122);
- if (!$board) {
- $dTag = sprintf('%s,%s,%s', $this->currentPleb->pubkey, date('Y'), $type);
- $note->setTags([['d', $dTag]]);
- }
- $note->setContent("$pubkey,$type");
- $this->signThisEvent = $note->toJson();
-};
-
-$checkElection = function () {
- if ($this->election->end_time?->isPast()) {
- $this->isNotClosed = false;
- }
-};
-
-$signEvent = function ($event) {
- $note = new NostrEvent();
- $note->setId($event['id']);
- $note->setSignature($event['sig']);
- $note->setKind($event['kind']);
- $note->setContent($event['content']);
- $note->setPublicKey($event['pubkey']);
- $note->setTags($event['tags']);
- $note->setCreatedAt($event['created_at']);
- $eventMessage = new EventMessage($note);
- $relay = new Relay(config('services.relay'));
- $relay->setMessage($eventMessage);
- $relay->send();
- Broadcast::on('votes')->as('newVote')->sendNow();
-};
-
-?>
-
- @volt
- @if($isAllowed)
+
- @php
+ ['icon' => 'fa-crown', 'title' => 'Präsidium'],
'board' => ['icon' => 'fa-users', 'title' => 'Vizepräsidium'],
@@ -227,7 +62,7 @@ $signEvent = function ($event) {
})
->sortByDesc('created_at')
->values();
- @endphp
+ ?>
- @endforeach
+
@@ -369,9 +204,9 @@ $signEvent = function ($event) {
- @if($currentPubkey)
+
- @php
+ candidates, true, 512, JSON_THROW_ON_ERROR))
->map(function ($c) use ($loadedEvents, $currentPubkey) {
$candidates = \App\Models\Profile::query()
@@ -425,7 +260,7 @@ $signEvent = function ($event) {
'candidates' => $candidates,
];
});
- @endphp
+ ?>
@@ -437,12 +272,12 @@ $signEvent = function ($event) {
- @if($isNotClosed)
+
- @else
+ label="Die Wahl ist geöffnet bis zum end_time?->timezone('Europe/Berlin')->format('d.m.Y H:i')); ?>"/>
+
- @endif
+
Wahl des Präsidiums
- @php
+
-
{{ $president['title'] }}
+
- @php
+ filter(fn ($event) => $event['pubkey'] === $currentPubkey)->firstWhere('type', 'presidency');
- @endphp
- @if($votedResult)
- Du hast "{{ $votedResult['votedFor']['name'] ?? 'error' }}" gewählt
- @else
+ ?>
+
+ Du hast "" gewählt
+
Wähle deinen Kandidaten für das Präsidium.
- @endif
+
@@ -543,21 +378,21 @@ $signEvent = function ($event) {
@@ -573,7 +408,7 @@ $signEvent = function ($event) {
Präsidium Log {{ $loadedEvents->count() }}
+ class="text-gray-400 dark:text-gray-500 font-medium">count()); ?>
@@ -607,29 +442,29 @@ $signEvent = function ($event) {
- @foreach($loadedEvents as $event)
+
{{ \Illuminate\Support\Str::limit($event['id'], 10) }}
+ class="font-medium">
- {{ $event['kind'] }}
+
- {{ $event['profile']['name'] ?? '' }}
+
- {{ $event['created_at'] }}
+
- {{ $event['votedFor']['name'] ?? '' }}
+
- {{ $event['type'] }}
+
- @endforeach
+
@@ -640,7 +475,7 @@ $signEvent = function ($event) {
Board Log {{ $loadedBoardEvents->count() }}
+ class="text-gray-400 dark:text-gray-500 font-medium">count()); ?>
@@ -674,29 +509,29 @@ $signEvent = function ($event) {
- @foreach($loadedBoardEvents as $event)
+
{{ \Illuminate\Support\Str::limit($event['id'], 10) }}
+ class="font-medium">
- {{ $event['kind'] }}
+
- {{ $event['profile']['name'] ?? '' }}
+
- {{ $event['created_at'] }}
+
- {{ $event['votedFor']['name'] ?? '' }}
+
- {{ $event['type'] }}
+
- @endforeach
+
@@ -707,10 +542,10 @@ $signEvent = function ($event) {
- @endif
+
- @else
+
@@ -721,8 +556,7 @@ $signEvent = function ($event) {
- @endif
+
- @endvolt
diff --git a/resources/views/livewire/association/members/admin.blade.php b/resources/views/livewire/association/members/admin.blade.php
new file mode 100644
index 0000000..6017995
--- /dev/null
+++ b/resources/views/livewire/association/members/admin.blade.php
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
Mitglieder
+
+ Du bist nicht berechtigt, Mitglieder zu bearbeiten.
+
+
+
+
+
+
+
diff --git a/resources/views/pages/association/news/index.blade.php b/resources/views/livewire/association/news/index.blade.php
similarity index 71%
rename from resources/views/pages/association/news/index.blade.php
rename to resources/views/livewire/association/news/index.blade.php
index 66f987d..2182b8b 100644
--- a/resources/views/pages/association/news/index.blade.php
+++ b/resources/views/livewire/association/news/index.blade.php
@@ -1,122 +1,8 @@
- fn()
- => \App\Models\Notification::query()
- ->orderBy('created_at', 'desc')
- ->get(),
- 'isAllowed' => false,
- 'canEdit' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
-]);
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
- if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) {
- $this->canEdit = true;
- }
- $this->isAllowed = true;
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- if (in_array($this->currentPleb->npub, config('einundzwanzig.config.current_board'), true)) {
- $this->canEdit = true;
- }
- $this->isAllowed = true;
- },
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-$save = function () {
- $this->form->validate();
-
- $this->validate([
- 'file' => 'required|file|mimes:pdf|max:1024',
- ]);
-
- $notification = \App\Models\Notification::query()
- ->orderBy('created_at', 'desc')
- ->create([
- 'einundzwanzig_pleb_id' => $this->currentPleb->id,
- 'category' => $this->form->category,
- 'name' => $this->form->name,
- 'description' => $this->form->description,
- ]);
-
- $notification
- ->addMedia($this->file->getRealPath())
- ->usingName($this->file->getClientOriginalName())
- ->toMediaCollection('pdf');
-
- $this->form->reset();
- $this->file = null;
-
- $this->news = \App\Models\Notification::query()
- ->orderBy('created_at', 'desc')
- ->get();
-};
-
-$delete = function ($id) {
- $notification = new WireNotification($this);
- $notification->confirm([
- 'title' => 'Post löschen',
- 'message' => 'Bist du sicher, dass du diesen Post löschen möchtest?',
- 'accept' => [
- 'label' => 'Ja, löschen',
- 'method' => 'deleteNow',
- 'params' => $id,
- ],
- ]);
-};
-
-$deleteNow = function ($id) {
- $notification = \App\Models\Notification::query()->find($id);
- $notification->delete();
- $this->news = \App\Models\Notification::query()
- ->orderBy('created_at', 'desc')
- ->get();
-};
-
-?>
-
- @volt
- @if($isAllowed)
+
@@ -151,17 +37,17 @@ $deleteNow = function ($id) {
Menu
@@ -174,25 +60,27 @@ $deleteNow = function ($id) {
- @forelse($news as $post)
-
+
+
+
+ alt="einundzwanzigPleb->profile?->name); ?>">
- {{ $post->name }}
+ name); ?>
- {{ $post->description }}
+ description); ?>
@@ -207,14 +95,14 @@ $deleteNow = function ($id) {
- {{ $post->einundzwanzigPleb->profile->name }}
+ einundzwanzigPleb->profile->name); ?>
{{ $post->created_at->format('d.m.Y') }}
+ class="text-gray-500">created_at->format('d.m.Y')); ?>
@@ -226,20 +114,21 @@ $deleteNow = function ($id) {
:href="url()->temporarySignedRoute('dl', now()->addMinutes(30), ['media' => $post->getFirstMedia('pdf')])"
label="Öffnen"
primary icon="cloud-arrow-down"/>
- @if($canEdit)
+
- @endif
+
- @empty
+
+
Keine News vorhanden.
- @endforelse
+
@@ -256,7 +145,7 @@ $deleteNow = function ($id) {
- @if($canEdit)
+
@@ -265,8 +154,16 @@ $deleteNow = function ($id) {
- @endif
+
@@ -302,7 +199,7 @@ $deleteNow = function ($id) {
- @else
+
@@ -315,7 +212,6 @@ $deleteNow = function ($id) {
- @endif
+
- @endvolt
diff --git a/resources/views/pages/association/profile.blade.php b/resources/views/livewire/association/profile.blade.php
similarity index 67%
rename from resources/views/pages/association/profile.blade.php
rename to resources/views/livewire/association/profile.blade.php
index f568709..561d880 100644
--- a/resources/views/pages/association/profile.blade.php
+++ b/resources/views/livewire/association/profile.blade.php
@@ -1,287 +1,6 @@
- false,
- 'showEmail' => true,
- 'fax' => '',
- 'email' => '',
- 'yearsPaid' => [],
- 'events' => [],
- 'payments' => [],
- 'amountToPay' => config('app.env') === 'production' ? 21000 : 1,
- 'currentYearIsPaid' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
-]);
-
-form(\App\Livewire\Forms\ApplicationForm::class);
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
- ->with([
- 'paymentEvents' => fn($query)
- => $query->where('year', date('Y')),
- ])
- ->where('pubkey', $this->currentPubkey)->first();
- $this->email = $this->currentPleb->email;
- $this->no = $this->currentPleb->no_email;
- $this->showEmail = !$this->no;
- if ($this->currentPleb->association_status === \App\Enums\AssociationStatus::ACTIVE) {
- $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
- }
- if ($this->currentPleb->paymentEvents->count() < 1) {
- $this->createPaymentEvent();
- $this->currentPleb->load('paymentEvents');
- }
- $this->loadEvents();
- $this->listenForPayment();
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
-
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
- ->with([
- 'paymentEvents' => fn($query)
- => $query->where('year', date('Y')),
- ])
- ->where('pubkey', $pubkey)->first();
- $this->email = $this->currentPleb->email;
- $this->no = $this->currentPleb->no_email;
- $this->showEmail = !$this->no;
- if ($this->currentPleb->association_status === \App\Enums\AssociationStatus::ACTIVE) {
- $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
- }
- if ($this->currentPleb->paymentEvents->count() < 1) {
- $this->createPaymentEvent();
- $this->currentPleb->load('paymentEvents');
- }
- $this->loadEvents();
- $this->listenForPayment();
- },
- 'nostrLoggedOut' => function () {
- \App\Support\NostrAuth::logout();
-
- $this->currentPubkey = null;
- $this->currentPleb = null;
- $this->yearsPaid = [];
- $this->events = [];
- $this->payments = [];
- $this->qrCode = null;
- $this->amountToPay = config('app.env') === 'production' ? 21000 : 1;
- $this->currentYearIsPaid = false;
- },
-]);
-
-updated([
- 'no' => function () {
- $this->showEmail = !$this->no;
- $this->currentPleb->update([
- 'no_email' => $this->no,
- ]);
- },
- 'fax' => function () {
- $this->js('alert("Markus Turm wird sich per Fax melden!")');
- },
-]);
-
-$saveEmail = function () {
- $this->validate([
- 'email' => 'required|email',
- ]);
- $this->currentPleb->update([
- 'email' => $this->email,
- ]);
- $notification = new Notification($this);
- $notification->success('E-Mail Adresse gespeichert.');
-};
-
-$pay = function ($comment) {
- $paymentEvent = $this->currentPleb
- ->paymentEvents()
- ->where('year', date('Y'))
- ->first();
- if ($paymentEvent->btc_pay_invoice) {
- return redirect('https://pay.einundzwanzig.space/i/'.$paymentEvent->btc_pay_invoice);
- }
- try {
- $response = Http::withHeaders([
- 'Authorization' => 'token '.config('services.btc_pay.api_key'),
- ])->post(
- 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices',
- [
- 'amount' => $this->amountToPay,
- 'metadata' => [
- 'orderId' => $comment,
- 'orderUrl' => url()->route('association.profile'),
- 'itemDesc' => 'Mitgliedsbeitrag '.date('Y').' von nostr:'.$this->currentPleb->npub,
- 'posData' => [
- 'event' => $paymentEvent->event_id,
- 'pubkey' => $this->currentPleb->pubkey,
- 'npub' => $this->currentPleb->npub,
- ],
- ],
- 'checkout' => [
- 'expirationMinutes' => 60 * 24,
- 'redirectURL' => url()->route('association.profile'),
- 'redirectAutomatically' => true,
- 'defaultLanguage' => 'de',
- ],
- ],
- )->throw();
- $paymentEvent->btc_pay_invoice = $response->json()['id'];
- $paymentEvent->save();
-
- return redirect($response->json()['checkoutLink']);
- } catch (Exception $e) {
- $notification = new Notification($this);
- $notification->error(
- 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: '.$e->getMessage(),
- );
- }
-};
-
-$listenForPayment = function () {
- $paymentEvent = $this->currentPleb
- ->paymentEvents()
- ->where('year', date('Y'))
- ->first();
- if ($paymentEvent->btc_pay_invoice) {
- $response = Http::withHeaders([
- 'Authorization' => 'token '.config('services.btc_pay.api_key'),
- ])
- ->get(
- 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/'.$paymentEvent->btc_pay_invoice,
- );
- if ($response->json()['status'] === 'Expired') {
- $paymentEvent->btc_pay_invoice = null;
- $paymentEvent->paid = false;
- $paymentEvent->save();
- }
- if ($response->json()['status'] === 'Settled') {
- $paymentEvent->paid = true;
- $paymentEvent->save();
- $this->currentYearIsPaid = true;
- }
- }
- if ($paymentEvent->paid) {
- $this->currentYearIsPaid = true;
- }
- $paymentEvent = $paymentEvent->refresh();
- $this->payments = $this->currentPleb
- ->paymentEvents()
- ->where('paid', true)
- ->get();
-};
-
-$save = function ($type) {
- $this->form->validate();
- if (!$this->form->check) {
- $this->js('alert("Du musst den Statuten zustimmen.")');
- return;
- }
-
- $this->currentPleb
- ->update([
- 'association_status' => $type,
- ]);
-};
-
-$createPaymentEvent = function () {
- $note = new NostrEvent();
- $note->setKind(32121);
- $note->setContent(
- 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr '.date(
- 'Y',
- ).'. Bitte bezahle den Betrag von '.number_format($this->amountToPay, 0, ',', '.').' Satoshis.',
- );
- $note->setTags([
- ['d', $this->currentPleb->pubkey.','.date('Y')],
- ['zap', 'daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6', config('services.relay'), '1'],
- ]);
- $signer = new Sign();
- $signer->signEvent($note, config('services.nostr'));
-
- $eventMessage = new EventMessage($note);
-
- $relayUrl = config('services.relay');
- $relay = new Relay($relayUrl);
- $relay->setMessage($eventMessage);
- $result = $relay->send();
-
- $this->currentPleb->paymentEvents()->create([
- 'year' => date('Y'),
- 'event_id' => $result->eventId,
- 'amount' => $this->amountToPay,
- ]);
-};
-
-$loadEvents = function () {
- $subscription = new Subscription();
- $subscriptionId = $subscription->setId();
-
- $filter1 = new Filter();
- $filter1->setKinds([32121]);
- $filter1->setAuthors(['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6']);
- $filters = [$filter1];
-
- $requestMessage = new RequestMessage($subscriptionId, $filters);
-
- $relays = [
- new Relay(config('services.relay')),
- ];
- $relaySet = new RelaySet();
- $relaySet->setRelays($relays);
-
- $request = new Request($relaySet, $requestMessage);
- $response = $request->send();
-
- $this->events = collect($response[config('services.relay')])
- ->map(function ($event) {
- if (!isset($event->event)) {
- return false;
- }
- return [
- 'id' => $event->event->id,
- 'kind' => $event->event->kind,
- 'content' => $event->event->content,
- 'pubkey' => $event->event->pubkey,
- 'tags' => $event->event->tags,
- 'created_at' => $event->event->created_at,
- ];
- })
- ->filter()
- ->unique('id')
- ->toArray();
-};
-
-?>
-
- @volt
@@ -314,39 +33,8 @@ $loadEvents = function () {
class="text-sm font-medium text-orange-500 dark:text-orange-400">Status
- {{--
-
-
-
-
- My Notifications
-
- --}}
-
- {{----}}
@@ -466,7 +154,6 @@ $loadEvents = function () {
@endif
- {{-- https://v.nostr.build/bomfuwLnOTIDrP4y.mp4 --}}
- {{--
- @if($currentPubkey && !$currentPleb->application_for && $currentPleb->association_status->value < 2)
-
- passives Mitglied werden
-
-
- Passivmitglieder haben kein Stimmrecht. Firmen können nur Passivmitglieder werden und zahlen das 100-fache des festgelegten Beitrags.
-
-
-
-
-
- @endif
- --}}
-
@if($currentPubkey && !$currentPleb->application_for && $currentPleb->association_status->value < 2)
@@ -547,7 +209,7 @@ $loadEvents = function () {
+ wire:click="save({{ AssociationStatus::PASSIVE() }})"/>
@endif
@@ -602,35 +264,6 @@ $loadEvents = function () {
@endif
-
- @if($currentPubkey && $currentPleb->application_for)
-
-
-
-
-
-
-
-
- Du hast dich erfolgreich mit folgendem Grund beworben:
-
-
{{ $currentPleb->application_text }}
-
-
-
- Schaue später vorbei, denn nun muss jemand aus dem Vorstand deine
- Bewerbung prüfen.
-
-
-
-
-
- @endif
-
-
@if($currentPleb && $currentPleb->association_status->value > 1)
@@ -790,5 +423,4 @@ $loadEvents = function () {
- @endvolt
diff --git a/resources/views/pages/association/project-support/form/create.blade.php b/resources/views/livewire/association/project-support/form/create.blade.php
similarity index 55%
rename from resources/views/pages/association/project-support/form/create.blade.php
rename to resources/views/livewire/association/project-support/form/create.blade.php
index f2f36f0..71838e7 100644
--- a/resources/views/pages/association/project-support/form/create.blade.php
+++ b/resources/views/livewire/association/project-support/form/create.blade.php
@@ -1,77 +1,6 @@
- false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
-]);
-
-usesFileUploads();
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
- $this->isAllowed = true;
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- $this->isAllowed = true;
- },
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-$save = function () {
- $this->form->validate();
-
- $projectProposal = \App\Models\ProjectProposal::query()->create([
- ...$this->form->all(),
- 'einundzwanzig_pleb_id' => $this->currentPleb->id,
- ]);
- if ($this->image) {
- $this->validate([
- 'image' => 'image|max:1024',
- ]);
- $projectProposal
- ->addMedia($this->image->getRealPath())
- ->toMediaCollection('main');
- }
-
- return redirect()->route('association.projectSupport');
-};
-
-?>
-
- @volt
- @if($isAllowed)
+
- @error('form.description')
{{ $message }} @enderror
+ getBag($__errorProps ?? 'default');
+if ($__bag->has($__errorArgs)) :
+if (isset($message)) { $__messageOriginal = $message; }
+$message = $__bag->first($__errorArgs); ?>
+
+
- {{ __('Zurück') }}
+
- {{ __('Save') }}
+
- @else
+
@@ -151,7 +97,6 @@ $save = function () {
- @endif
+
- @endvolt
diff --git a/resources/views/pages/association/project-support/form/[ProjectProposal:slug].blade.php b/resources/views/livewire/association/project-support/form/edit.blade.php
similarity index 56%
rename from resources/views/pages/association/project-support/form/[ProjectProposal:slug].blade.php
rename to resources/views/livewire/association/project-support/form/edit.blade.php
index 39fec6a..7837aff 100644
--- a/resources/views/pages/association/project-support/form/[ProjectProposal:slug].blade.php
+++ b/resources/views/livewire/association/project-support/form/edit.blade.php
@@ -1,81 +1,6 @@
- fn() => $projectProposal,
- 'image',
- 'isAllowed' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
-]);
-
-usesFileUploads();
-
-mount(function (ProjectProposal $projectProposal) {
- if (NostrAuth::check()) {
- $this->currentPubkey = NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
- $this->isAllowed = true;
- $this->form->fill($projectProposal->toArray());
- $this->image = $projectProposal->getFirstMedia('main');
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- $this->isAllowed = true;
- },
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-$save = function () {
- $this->form->validate();
- if ($this->image && method_exists($this->image, 'temporaryUrl')) {
- $this->validate([
- 'image' => 'nullable|image|max:1024',
- ]);
- $this->projectProposal
- ->addMedia($this->image->getRealPath())
- ->toMediaCollection('main');
- }
-
- $this->projectProposal->update([
- ...$this->form->except('id', 'slug'),
- ]);
-
- return redirect()->route('association.projectSupport');
-};
-
-?>
-
-
- @volt
+
- @if($isAllowed)
+
- @error('form.description')
{{ $message }} @enderror
+ getBag($__errorProps ?? 'default');
+if ($__bag->has($__errorArgs)) :
+if (isset($message)) { $__messageOriginal = $message; }
+$message = $__bag->first($__errorArgs); ?>
+
+
- {{ __('Zurück') }}
+
- {{ __('Speichern') }}
+
- @else
+
@@ -164,7 +106,6 @@ $save = function () {
- @endif
+
- @endvolt
diff --git a/resources/views/livewire/association/project-support/index.blade.php b/resources/views/livewire/association/project-support/index.blade.php
new file mode 100644
index 0000000..6e14900
--- /dev/null
+++ b/resources/views/livewire/association/project-support/index.blade.php
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+ Einundzwanzig Projektunterstützungen
+
+
+
+
+
+
+
+
+
+
+ @if($currentPleb && $currentPleb->association_status->value > 1 && $currentPleb->paymentEvents()->where('year', date('Y'))->where('paid', true)->exists())
+
+ @endif
+
+
+
+
+
+
+
+
+
+ Alle
+
+
+
+
+ Neu
+
+
+
+
+ Unterstützt
+
+
+
+
+ Abgelehnt
+
+
+
+
+
{{ $projects->count() }} Projekte
+
+
+
+ @foreach($this->projects as $project)
+
+ @endforeach
+
+
+
+
+
diff --git a/resources/views/pages/association/project-support/[ProjectProposal:slug].blade.php b/resources/views/livewire/association/project-support/show.blade.php
similarity index 56%
rename from resources/views/pages/association/project-support/[ProjectProposal:slug].blade.php
rename to resources/views/livewire/association/project-support/show.blade.php
index 3b49053..250a7b9 100644
--- a/resources/views/pages/association/project-support/[ProjectProposal:slug].blade.php
+++ b/resources/views/livewire/association/project-support/show.blade.php
@@ -1,114 +1,7 @@
- fn() => $projectProposal,
- 'isAllowed' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
- 'ownVoteExists' => false,
- 'boardVotes' => fn() => $this->getBoardVotes(),
- 'otherVotes' => fn() => $this->getOtherVotes(),
-]);
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->handleNostrLoggedIn($this->currentPubkey);
- }
-});
-
-on([
- 'nostrLoggedIn' => fn($pubkey) => $this->handleNostrLoggedIn($pubkey),
- 'nostrLoggedOut' => fn() => $this->handleNostrLoggedOut(),
-]);
-
-$approve = fn() => $this->handleApprove();
-$notApprove = fn() => $this->handleNotApprove();
-
-$getBoardVotes = function () {
- return Vote::query()
- ->where('project_proposal_id', $this->projectProposal->id)
- ->whereHas('einundzwanzigPleb', fn($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board')))
- ->get();
-};
-
-$getOtherVotes = function () {
- return Vote::query()
- ->where('project_proposal_id', $this->projectProposal->id)
- ->whereDoesntHave(
- 'einundzwanzigPleb',
- fn($q) => $q->whereIn('npub', config('einundzwanzig.config.current_board'))
- )
- ->get();
-};
-
-$handleNostrLoggedIn = function ($pubkey) {
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- $this->isAllowed = true;
- $this->ownVoteExists = Vote::query()
- ->where('project_proposal_id', $this->projectProposal->id)
- ->where('einundzwanzig_pleb_id', $this->currentPleb->id)
- ->exists();
-};
-
-$handleNostrLoggedOut = function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
-};
-
-$handleApprove = function () {
- Vote::query()->updateOrCreate([
- 'project_proposal_id' => $this->projectProposal->id,
- 'einundzwanzig_pleb_id' => $this->currentPleb->id,
- ], [
- 'value' => true,
- ]);
- $this->form->reset();
- $this->ownVoteExists = true;
- $this->boardVotes = $this->getBoardVotes();
- $this->otherVotes = $this->getOtherVotes();
-};
-
-$handleNotApprove = function () {
- $this->form->validate();
-
- Vote::query()->updateOrCreate([
- 'project_proposal_id' => $this->projectProposal->id,
- 'einundzwanzig_pleb_id' => $this->currentPleb->id,
- ], [
- 'value' => false,
- ]);
- $this->form->reset();
- $this->ownVoteExists = true;
-};
-
-?>
-
- @volt
- @if($projectProposal->accepted || $isAllowed)
+ accepted || $isAllowed): ?>
@@ -118,7 +11,7 @@ $handleNotApprove = function () {
- {{ $projectProposal->created_at->translatedFormat('d.m.Y') }}
+ created_at->translatedFormat('d.m.Y')); ?>
- {{ $projectProposal->name }}
+ name); ?>
- {!! $projectProposal->description !!}
+ description; ?>
@@ -145,12 +38,12 @@ $handleNotApprove = function () {
Eingereicht von
{{ $projectProposal->einundzwanzigPleb?->profile->name ?? str($projectProposal->einundzwanzigPleb->npub)->limit(32) }}
+ class="font-semibold text-gray-800 dark:text-gray-100">einundzwanzigPleb?->profile->name ?? str($projectProposal->einundzwanzigPleb->npub)->limit(32)); ?>
@@ -158,56 +51,31 @@ $handleNotApprove = function () {
- {{ number_format($projectProposal->support_in_sats, 0, ',', '.') }} Sats
+ support_in_sats, 0, ',', '.')); ?> Sats
-
-
- {{--
-
- Ablehnungen ({{ count($reasons) }})
-
-
- @foreach($reasons as $reason)
-
-
-
-
-
-
- {{ $reason->einundzwanzigPleb->profile->name }}
-
-
{{ $reason->reason }}
-
-
- @endforeach
-
-
--}}
-
- @if($isAllowed && !$projectProposal->accepted)
+ accepted): ?>
- @if(!$ownVoteExists)
+
Ablehnen
- {{-- --}}
- @else
+
Du hast bereits abgestimmt.
- @endif
+
- Zustimmungen des Vorstands ({{ count($boardVotes->where('value', 1)) }})
+ Zustimmungen des Vorstands (where('value', 1))); ?>)
@@ -243,7 +110,7 @@ $handleNotApprove = function () {
- Ablehnungen des Vorstands ({{ count($boardVotes->where('value', 0)) }})
+ Ablehnungen des Vorstands (where('value', 0))); ?>)
@@ -252,8 +119,7 @@ $handleNotApprove = function () {
- Zustimmungen der übrigen Mitglieder ({{ count($otherVotes->where('value', 1)) }}
- )
+ Zustimmungen der übrigen Mitglieder (where('value', 1))); ?>)
@@ -262,18 +128,18 @@ $handleNotApprove = function () {
- Ablehnungen der übrigen Mitglieder ({{ count($otherVotes->where('value', 0)) }})
+ Ablehnungen der übrigen Mitglieder (where('value', 0))); ?>)
- @endif
+
- @else
+
@@ -286,7 +152,6 @@ $handleNotApprove = function () {
- @endif
+
- @endvolt
diff --git a/resources/views/pages/changelog.blade.php b/resources/views/livewire/changelog.blade.php
similarity index 81%
rename from resources/views/pages/changelog.blade.php
rename to resources/views/livewire/changelog.blade.php
index 3a32080..77b2805 100644
--- a/resources/views/pages/changelog.blade.php
+++ b/resources/views/livewire/changelog.blade.php
@@ -1,43 +1,4 @@
- []]);
-
-mount(function () {
- $output = shell_exec('git log -n1000 --pretty=format:"%H|%s|%an|%ad" --date=format:"%Y-%m-%d %H:%M:%S"');
- $lines = explode("\n", trim($output));
- $entries = [];
-
- foreach ($lines as $line) {
- [$hash, $message, $author, $date] = explode('|', $line);
- $entries[] = [
- 'hash' => $hash,
- 'message' => $message,
- 'author' => $author,
- 'date' => $date,
- ];
- }
- $this->entries = $entries;
-});
-
-?>
-
- @volt
@@ -103,5 +64,4 @@ mount(function () {
- @endvolt
diff --git a/resources/views/pages/einundzwanzig-feed/index.blade.php b/resources/views/livewire/einundzwanzig-feed/index.blade.php
similarity index 72%
rename from resources/views/pages/einundzwanzig-feed/index.blade.php
rename to resources/views/livewire/einundzwanzig-feed/index.blade.php
index 30b1f50..d2a03d0 100644
--- a/resources/views/pages/einundzwanzig-feed/index.blade.php
+++ b/resources/views/livewire/einundzwanzig-feed/index.blade.php
@@ -1,58 +1,4 @@
- []],
-);
-
-state(
- ['newEvents' => false],
-);
-
-mount(function () {
- $this->events = \App\Models\Event::query()
- ->where('type', 'root')
- ->orderBy('created_at', 'desc')
- ->with([
- 'renderedEvent',
- ])
- ->get()
- ->toArray();
-});
-
-on(['echo:events,.newEvents' => function () {
- $this->newEvents = true;
-}]);
-
-$loadMore = function () {
- // Load more events
- $this->newEvents = false;
-};
-
-?>
-
- @volt
@if($newEvents)
@@ -62,7 +8,7 @@ $loadMore = function () {
@@ -94,7 +40,6 @@ $loadMore = function () {
{{ $event['rendered_event']['profile_name'] }}
- {{--{{ $event['event_id'] }}
--}}
@@ -114,5 +59,4 @@ $loadMore = function () {
@endforeach
- @endvolt
diff --git a/resources/views/pages/meetups/grid.blade.php b/resources/views/livewire/meetups/grid.blade.php
similarity index 96%
rename from resources/views/pages/meetups/grid.blade.php
rename to resources/views/livewire/meetups/grid.blade.php
index c51358a..18f8d73 100644
--- a/resources/views/pages/meetups/grid.blade.php
+++ b/resources/views/livewire/meetups/grid.blade.php
@@ -1,32 +1,4 @@
-
-
-
- @volt
@@ -247,5 +219,4 @@ name('meetups.grid');
- @endvolt
diff --git a/resources/views/livewire/meetups/mockup.blade.php b/resources/views/livewire/meetups/mockup.blade.php
new file mode 100644
index 0000000..8071c70
--- /dev/null
+++ b/resources/views/livewire/meetups/mockup.blade.php
@@ -0,0 +1,35 @@
+
+
+
+
Meetups
+
+ @foreach($events as $event)
+
+
+
+
+ Name: {{ collect($event['tags'])->firstWhere(0, 'title')[1] }}
+
+
+ Beschreibung: {{ $event['content'] }}
+
+
+ @dump($event)
+
+
+
+
+ @endforeach
+
+
+
diff --git a/resources/views/livewire/meetups/table.blade.php b/resources/views/livewire/meetups/table.blade.php
new file mode 100644
index 0000000..69f16a1
--- /dev/null
+++ b/resources/views/livewire/meetups/table.blade.php
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/resources/views/livewire/meetups/worldmap.blade.php b/resources/views/livewire/meetups/worldmap.blade.php
new file mode 100644
index 0000000..77fb081
--- /dev/null
+++ b/resources/views/livewire/meetups/worldmap.blade.php
@@ -0,0 +1,46 @@
+@push('scripts')
+
+
+
+
+@endpush
+
+
+
+
diff --git a/resources/views/livewire/welcome.blade.php b/resources/views/livewire/welcome.blade.php
new file mode 100644
index 0000000..3c34f11
--- /dev/null
+++ b/resources/views/livewire/welcome.blade.php
@@ -0,0 +1,5 @@
+
+
+ TEST
+
+
diff --git a/resources/views/pages/association/election/admin/[Election:year].blade.php b/resources/views/pages/association/election/admin/[Election:year].blade.php
deleted file mode 100644
index 442c5d6..0000000
--- a/resources/views/pages/association/election/admin/[Election:year].blade.php
+++ /dev/null
@@ -1,257 +0,0 @@
- false,
- 'currentPubkey' => null,
- 'votes' => null,
- 'boardVotes' => null,
- 'events' => null,
- 'boardEvents' => null,
- 'election' => fn() => $election,
- 'signThisEvent' => '',
- 'plebs' => fn()
- => \App\Models\EinundzwanzigPleb::query()
- ->with(['profile'])
- ->whereIn('association_status', [3, 4])
- ->orderBy('association_status', 'desc')
- ->get()
- ->toArray(),
- 'electionConfig' => fn()
- => collect(json_decode($this->election->candidates, true, 512, JSON_THROW_ON_ERROR))
- ->map(fn($c)
- => [
- 'type' => $c['type'],
- 'c' => $c['c'],
- 'candidates' => \App\Models\Profile::query()
- ->whereIn('pubkey', $c['c'])
- ->get()
- ->map(fn($p)
- => [
- 'pubkey' => $p->pubkey,
- 'name' => $p->name,
- 'picture' => $p->picture,
- ]),
- ]),
-]);
-
-mount(fn()
- => [
- $this->loadEvents(),
- $this->loadBoardEvents(),
- $this->loadVotes(),
- $this->loadBoardVotes(),
-]);
-
-on([
- 'nostrLoggedOut' => function () {
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-on([
- 'nostrLoggedIn' => function($pubkey) {
- $this->currentPubkey = $pubkey;
- $allowedPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- ];
- if(in_array($this->currentPubkey, $allowedPubkeys, true)) {
- $this->isAllowed = true;
- }
- dd($this->isAllowed);
- },
- 'echo:votes,.newVote' => fn()
- => [
- $this->loadEvents(),
- $this->loadBoardEvents(),
- $this->loadVotes(),
- $this->loadBoardVotes(),
- ],
-]);
-
-$loadVotes = function () {
- $this->votes = collect($this->events)
- ->map(fn($event)
- => [
- 'created_at' => $event['created_at'],
- 'pubkey' => $event['pubkey'],
- 'forpubkey' => $this->fetchProfile($event['content']),
- 'type' => str($event['content'])->after(',')->toString(),
- ])
- ->sortByDesc('created_at')
- ->unique(fn($event) => $event['pubkey'] . $event['type'])
- ->values()
- ->groupBy('type')
- ->map(fn($votes)
- => [
- 'type' => $votes[0]['type'],
- 'votes' => $votes->groupBy('forpubkey')->map(fn($group) => ['count' => $group->count()])->toArray(),
- ])
- ->values()
- ->toArray();
-};
-
-$loadBoardVotes = function () {
- $this->boardVotes = collect($this->boardEvents)
- ->map(fn($event)
- => [
- 'created_at' => $event['created_at'],
- 'pubkey' => $event['pubkey'],
- 'forpubkey' => $this->fetchProfile($event['content']),
- 'type' => str($event['content'])->after(',')->toString(),
- ])
- ->sortByDesc('created_at')
- ->values()
- ->groupBy('type')
- ->map(fn($votes)
- => [
- 'type' => $votes[0]['type'],
- 'votes' => $votes->groupBy('forpubkey')->map(fn($group) => ['count' => $group->count()])->toArray(),
- ])
- ->values()
- ->toArray();
-};
-
-$loadEvents = function () {
- $this->events = $this->loadNostrEvents([32122]);
-};
-
-$loadBoardEvents = function () {
- $this->boardEvents = $this->loadNostrEvents([2121]);
-};
-
-$fetchProfile = function ($content) {
- $pubkey = str($content)->before(',')->toString();
- $profile = \App\Models\Profile::query()->where('pubkey', $pubkey)->first();
- if (!$profile) {
- Artisan::call(\App\Console\Commands\Nostr\FetchProfile::class, ['--pubkey' => $pubkey]);
- $profile = \App\Models\Profile::query()->where('pubkey', $pubkey)->first();
- }
- return $profile->pubkey;
-};
-
-$loadNostrEvents = function ($kinds) {
- $subscription = new Subscription();
- $subscriptionId = $subscription->setId();
- $filter = new Filter();
- $filter->setKinds($kinds);
- $requestMessage = new RequestMessage($subscriptionId, [$filter]);
- $relaySet = new RelaySet();
- $relaySet->setRelays([new Relay(config('services.relay'))]);
- $request = new Request($relaySet, $requestMessage);
- $response = $request->send();
- return collect($response[config('services.relay')])
- ->map(function($event) {
- if(!isset($event->event)) {
- return false;
- }
- return [
- 'id' => $event->event->id,
- 'kind' => $event->event->kind,
- 'content' => $event->event->content,
- 'pubkey' => $event->event->pubkey,
- 'tags' => $event->event->tags,
- 'created_at' => $event->event->created_at,
- ];
- })
- ->filter()
- ->toArray();
-};
-
-?>
-
-
- @volt
- @php
- $positions = [
- 'presidency' => ['icon' => 'fa-crown', 'title' => 'Präsidium'],
- 'board' => ['icon' => 'fa-users', 'title' => 'Vorstandsmitglieder'],
- ];
- @endphp
-
- @if($isAllowed)
-
-
-
-
-
-
-
-
-
- Wahl des Vorstands {{ $election->year }}
-
-
-
-
-
- @php
- $president = $positions['presidency'];
- $board = $positions['board'];
- @endphp
-
-
-
-
-
- {{ $president['title'] }}
-
-
-
-
-
-
-
-
-
- {{ $board['title'] }}
-
-
-
-
-
-
-
-
-
-
-
- @else
-
-
-
-
Mitglieder
-
- Du bist nicht berechtigt, Mitglieder zu bearbeiten.
-
-
-
-
- @endif
-
- @endvolt
-
diff --git a/resources/views/pages/association/election/index.blade.php b/resources/views/pages/association/election/index.blade.php
deleted file mode 100644
index 9d41f7c..0000000
--- a/resources/views/pages/association/election/index.blade.php
+++ /dev/null
@@ -1,103 +0,0 @@
- false]);
-state(['currentPubkey' => null]);
-state(['elections' => []]);
-
-mount(function () {
- $this->elections = \App\Models\Election::query()
- ->get()
- ->toArray();
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $logPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- ];
- if (in_array($this->currentPubkey, $logPubkeys, true)) {
- $this->isAllowed = true;
- }
- }
-});
-
-on([
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
- ->where('pubkey', $pubkey)->first();
- $logPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- ];
- if (in_array($this->currentPubkey, $logPubkeys, true)) {
- $this->isAllowed = true;
- }
- },
-]);
-
-$saveElection = function ($index) {
- $election = $this->elections[$index];
- $electionModel = \App\Models\Election::find($election['id']);
- $electionModel->candidates = $election['candidates'];
- $electionModel->save();
-};
-
-?>
-
-
- @volt
-
- @if($isAllowed)
-
- @foreach($elections as $election)
-
-
- {{ $election['year'] }}
-
-
-
-
-
-
-
-
- @endforeach
-
- @else
-
-
-
-
Einstellungen
-
- Du bist nicht berechtigt, die Einstellungen zu bearbeiten.
-
-
-
-
- @endif
-
- @endvolt
-
diff --git a/resources/views/pages/association/members/admin.blade.php b/resources/views/pages/association/members/admin.blade.php
deleted file mode 100644
index 7629c13..0000000
--- a/resources/views/pages/association/members/admin.blade.php
+++ /dev/null
@@ -1,93 +0,0 @@
- false]);
-state(['currentPubkey' => null]);
-state(['members' => []]);
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
- ->where('pubkey', $this->currentPubkey )->first();
- $allowedPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
- 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
- '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
- 'acbcec475a1a4f9481939ecfbd1c3d111f5b5a474a39ae039bbc720fdd305bec',
- ];
- if (in_array($this->currentPubkey, $allowedPubkeys, true)) {
- $this->isAllowed = true;
- }
- }
-});
-
-on([
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- },
-]);
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()
- ->where('pubkey', $pubkey)->first();
- $allowedPubkeys = [
- '0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033',
- '430169631f2f0682c60cebb4f902d68f0c71c498fd1711fd982f052cf1fd4279',
- '7acf30cf60b85c62b8f654556cc21e4016df8f5604b3b6892794f88bb80d7a1d',
- 'f240be2b684f85cc81566f2081386af81d7427ea86250c8bde6b7a8500c761ba',
- '19e358b8011f5f4fc653c565c6d4c2f33f32661f4f90982c9eedc292a8774ec3',
- 'acbcec475a1a4f9481939ecfbd1c3d111f5b5a474a39ae039bbc720fdd305bec',
- ];
- if (in_array($this->currentPubkey, $allowedPubkeys, true)) {
- $this->isAllowed = true;
- }
- },
-]);
-
-?>
-
-
- @volt
-
- @if($isAllowed)
-
-
-
- @else
-
-
-
-
Mitglieder
-
- Du bist nicht berechtigt, Mitglieder zu bearbeiten.
-
-
-
-
- @endif
-
- @endvolt
-
diff --git a/resources/views/pages/association/project-support/index.blade.php b/resources/views/pages/association/project-support/index.blade.php
deleted file mode 100644
index effe6af..0000000
--- a/resources/views/pages/association/project-support/index.blade.php
+++ /dev/null
@@ -1,187 +0,0 @@
- 'all',])->url();
-
-state([
- 'search' => '',
- 'projects' => fn()
- => \App\Models\ProjectProposal::query()
- ->with([
- 'einundzwanzigPleb.profile',
- 'votes',
- ])
- ->orderBy('created_at', 'desc')
- ->get(),
- 'isAllowed' => false,
- 'currentPubkey' => null,
- 'currentPleb' => null,
-]);
-
-updated([
- 'search' => function () {
- $this->projects = \App\Models\ProjectProposal::query()
- ->with([
- 'einundzwanzigPleb.profile',
- 'votes',
- ])
- ->where(function ($query) {
- $query
- ->where('name', 'ilike', '%'.$this->search.'%')
- ->orWhere('description', 'ilike', '%'.$this->search.'%')
- ->orWhereHas('einundzwanzigPleb.profile', function ($q) {
- $q->where('name', 'ilike', '%'.$this->search.'%');
- });
- })
- ->orderBy('created_at', 'desc')
- ->get();
- },
-]);
-
-$projects = computed(function () {
- return $this->projects;
-});
-
-mount(function () {
- if (\App\Support\NostrAuth::check()) {
- $this->currentPubkey = \App\Support\NostrAuth::pubkey();
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $this->currentPubkey)->first();
- $this->isAllowed = true;
- }
-});
-
-on([
- 'nostrLoggedIn' => function ($pubkey) {
- \App\Support\NostrAuth::login($pubkey);
- $this->currentPubkey = $pubkey;
- $this->currentPleb = \App\Models\EinundzwanzigPleb::query()->where('pubkey', $pubkey)->first();
- $this->isAllowed = true;
- },
- 'nostrLoggedOut' => function () {
- $this->isAllowed = false;
- $this->currentPubkey = null;
- $this->currentPleb = null;
- },
-]);
-
-$confirmDelete = function ($id) {
- $notification = new Notification($this);
- $notification->confirm([
- 'title' => 'Projektunterstützung löschen',
- 'message' => 'Bist du sicher, dass du diese Projektunterstützung löschen möchtest?',
- 'accept' => [
- 'label' => 'Ja, löschen',
- 'method' => 'delete',
- 'params' => $id,
- ],
- ]);
-};
-
-$setFilter = function ($filter) {
- $this->activeFilter = $filter;
-};
-
-$delete = function ($id) {
- \App\Models\ProjectProposal::query()->findOrFail($id)->delete();
- $this->projects = \App\Models\ProjectProposal::query()
- ->with([
- 'einundzwanzigPleb.profile',
- 'votes',
- ])
- ->orderBy('created_at', 'desc')
- ->get();
-};
-
-?>
-
-
- @volt
-
-
-
-
-
-
-
-
-
- Einundzwanzig Projektunterstützungen
-
-
-
-
-
-
-
-
-
-
- @if($currentPleb && $currentPleb->association_status->value > 1 && $currentPleb->paymentEvents()->where('year', date('Y'))->where('paid', true)->exists())
-
- @endif
-
-
-
-
-
-
-
-
-
- Alle
-
-
-
-
- Neu
-
-
-
-
- Unterstützt
-
-
-
-
- Abgelehnt
-
-
-
-
-
{{ $this->projects->count() }}Projekte
-
-
-
-
- @foreach($this->projects as $project)
-
- @endforeach
-
-
-
-
- @endvolt
-
diff --git a/resources/views/pages/index.blade.php b/resources/views/pages/index.blade.php
deleted file mode 100644
index 72964e2..0000000
--- a/resources/views/pages/index.blade.php
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- @volt
-
- TEST
-
- @endvolt
-
diff --git a/resources/views/pages/meetups/mockup.blade.php b/resources/views/pages/meetups/mockup.blade.php
deleted file mode 100644
index 384bc0c..0000000
--- a/resources/views/pages/meetups/mockup.blade.php
+++ /dev/null
@@ -1,145 +0,0 @@
- []]);
-state(['title' => '']);
-state(['description' => '']);
-state(['signThisEvent' => '']);
-
-mount(function () {
- $this->loadEvents();
-});
-
-$loadEvents = function() {
- $subscription = new Subscription();
- $subscriptionId = $subscription->setId();
-
- $filter1 = new Filter();
- $filter1->setKinds([31924]); // You can add multiple kind numbers
- $filter1->setLimit(25); // Limit to fetch only a maximum of 25 events
- $filters = [$filter1]; // You can add multiple filters.
-
- $requestMessage = new RequestMessage($subscriptionId, $filters);
-
- $relays = [
- new Relay('ws://nostream:8008'),
- ];
- $relaySet = new RelaySet();
- $relaySet->setRelays($relays);
-
- $request = new Request($relaySet, $requestMessage);
- $response = $request->send();
-
- $this->events = collect($response['ws://nostream:8008'])
- ->map(function($event) {
- if(!isset($event->event)) {
- return false;
- }
- return [
- 'id' => $event->event->id,
- 'kind' => $event->event->kind,
- 'content' => $event->event->content,
- 'pubkey' => $event->event->pubkey,
- 'tags' => $event->event->tags,
- 'created_at' => $event->event->created_at,
- ];
- })
- ->filter()
- ->toArray();
-};
-
-$save = function () {
- $note = new NostrEvent();
- $note->setContent($this->description);
- $note->setKind(31924);
- $note->setTags([
- ['d', str()->uuid()->toString()],
- ['title', $this->title],
- ]);
- $this->signThisEvent = $note->toJson();
-};
-
-$signEvent = function ($event) {
- $note = new NostrEvent();
- $note->setId($event['id']);
- $note->setSignature($event['sig']);
- $note->setKind($event['kind']);
- $note->setContent($event['content']);
- $note->setPublicKey($event['pubkey']);
- $note->setTags($event['tags']);
- $note->setCreatedAt($event['created_at']);
- $eventMessage = new EventMessage($note);
- $relayUrl = 'ws://nostream:8008';
- $relay = new Relay($relayUrl);
- $relay->setMessage($eventMessage);
- $result = $relay->send();
-
- $this->title = '';
- $this->description = '';
- $this->loadEvents();
-};
-
-?>
-
-
- @volt
-
-
-
Meetups
-
- @foreach($events as $event)
-
-
-
-
- Name: {{ collect($event['tags'])->firstWhere(0, 'title')[1] }}
-
-
- Beschreibung: {{ $event['content'] }}
-
-
- @dump($event)
-
-
-
-
- @endforeach
-
-
- @endvolt
-
diff --git a/resources/views/pages/meetups/table.blade.php b/resources/views/pages/meetups/table.blade.php
deleted file mode 100644
index d8c72cb..0000000
--- a/resources/views/pages/meetups/table.blade.php
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- @volt
-
-
-
- @endvolt
-
diff --git a/resources/views/pages/meetups/worldmap.blade.php b/resources/views/pages/meetups/worldmap.blade.php
deleted file mode 100644
index 4258598..0000000
--- a/resources/views/pages/meetups/worldmap.blade.php
+++ /dev/null
@@ -1,76 +0,0 @@
- []])
-
-?>
-
-@push('scripts')
-
-
-
-
-@endpush
-
-
- @volt
-
- @endvolt
-
diff --git a/routes/web.php b/routes/web.php
index 13eb67d..d84d0e8 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,5 +1,22 @@
name('logout');
+
+// Association Routes
+Route::livewire('/association/profile', Profile::name('association.profile'));
+
+Route::livewire('/association/election', ElectionIndex::class)->name('association.elections');
+Route::livewire('/association/election/{election:year}', ElectionShow::class)->name('association.election');
+Route::livewire('/association/election/admin/{election:year}', ElectionAdmin::class)->name('association.election.admin');
+
+Route::livewire('/association/members/admin', MembersAdmin::class)->name('association.members.admin');
+
+Route::livewire('/association/news', NewsIndex::class)->name('association.news');
+
+Route::livewire('/association/project-support', ProjectSupportIndex::class)->name('association.projectSupport');
+Route::livewire('/association/project-support/create', ProjectSupportCreate::class)->name('association.projectSupport.create');
+Route::livewire('/association/project-support/{projectProposal:slug}', ProjectSupportShow::class)->name('association.projectSupport.item');
+Route::livewire('/association/project-support/edit/{projectProposal:slug}', ProjectSupportEdit::class)->name('association.projectSupport.edit');
+
+// Einundzwanzig Feed
+Route::livewire('/einundzwanzig-feed', EinundzwanzigFeedIndex::class)->name('einundzwanzig-feed');
+
+// Meetups
+Route::livewire('/meetups/grid', MeetupsGrid::class)->name('meetups.grid');
+Route::livewire('/meetups/mockup', MeetupsMockup::class)->name('meetups.mockup');
+Route::livewire('/meetups/table', MeetupsTable::class)->name('meetups.table');
+Route::livewire('/meetups/worldmap', MeetupsWorldmap::class)->name('meetups.worldmap');
+
+// Other pages
+Route::livewire('/changelog', Changelog::class)->name('changelog');
+Route::livewire('/welcome', Welcome::class)->name('welcome');
diff --git a/storage/pail/.gitignore b/storage/pail/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/pail/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore