From 8d2cd3c26a6da1aacb845e582d4eeac8ee2ba411 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Wed, 9 Jul 2025 21:30:57 -0400 Subject: [PATCH 1/7] Adding Customer and Carrier audit logging --- CLAUDE.md | 183 +++++++ _ide_helper_actions.php | 14 + app/Actions/Audit/GetAuditLinkedData.php | 188 ++++++++ .../Carriers/GetCarrierAuditHistory.php | 96 ++++ .../Customers/GetCustomerAuditHistory.php | 93 ++++ app/Models/Carriers/Carrier.php | 4 +- app/Models/Customers/Customer.php | 4 +- composer.json | 1 + composer.lock | 86 +++- config/audit.php | 198 ++++++++ .../2025_07_10_004424_create_audits_table.php | 48 ++ resources/js/Components/AppSidebar.tsx | 190 ++++---- .../js/Components/Audit/AuditFieldValue.tsx | 77 +++ .../Components/Audit/AuditLinkedDataModal.tsx | 172 +++++++ resources/js/Components/Audit/AuditTable.tsx | 451 ++++++++++++++++++ .../js/Components/Audit/AuditTimeline.tsx | 281 +++++++++++ .../Components/Audit/CarrierAuditHistory.tsx | 122 +++++ .../Components/Audit/CustomerAuditHistory.tsx | 122 +++++ .../Carriers/Partials/CarrierDetails.tsx | 13 + .../Customers/Partials/CustomerDetails.tsx | 13 + routes/web.php | 8 + 21 files changed, 2266 insertions(+), 98 deletions(-) create mode 100644 CLAUDE.md create mode 100644 app/Actions/Audit/GetAuditLinkedData.php create mode 100644 app/Actions/Carriers/GetCarrierAuditHistory.php create mode 100644 app/Actions/Customers/GetCustomerAuditHistory.php create mode 100644 config/audit.php create mode 100644 database/migrations/2025_07_10_004424_create_audits_table.php create mode 100644 resources/js/Components/Audit/AuditFieldValue.tsx create mode 100644 resources/js/Components/Audit/AuditLinkedDataModal.tsx create mode 100644 resources/js/Components/Audit/AuditTable.tsx create mode 100644 resources/js/Components/Audit/AuditTimeline.tsx create mode 100644 resources/js/Components/Audit/CarrierAuditHistory.tsx create mode 100644 resources/js/Components/Audit/CustomerAuditHistory.tsx diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..bc0bee90 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,183 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +LoadPartner TMS - An open source Transportation Management System for freight brokers built with Laravel + Inertia.js + React + TypeScript. + +## Common Development Commands + +### Environment Setup +```bash +# Set up with Laravel Sail +sail up -d +sail artisan migrate +sail npm install +sail artisan key:generate +sail npm run dev + +# Fresh test data +sail artisan dev:refresh +``` + +### Development Workflow +```bash +# Run all dev services (server, queue, logs, vite) +composer run dev + +# Individual commands +sail artisan serve +sail npm run dev +sail artisan queue:listen --tries=1 +sail artisan pail --timeout=0 +``` + +### Testing & Quality +```bash +# Run tests (uses Pest) +sail artisan test +# or +sail pest + +# Run static analysis +sail artisan dev:check # Runs PHPStan + IDE helper generation +vendor/bin/phpstan analyse + +# Lint frontend +npm run lint +``` + +### Build & Production +```bash +# Build frontend assets +npm run build + +# Link storage for file uploads +sail artisan storage:link +``` + +## Architecture Overview + +### Laravel Actions Pattern +- All business logic organized in `app/Actions/` by domain +- Uses `lorisleiva/laravel-actions` package +- Each action has `handle()`, `asController()`, `rules()`, `authorize()` methods +- Actions serve as both controllers and reusable business logic + +### Multi-Tenant Architecture +- All models use `HasOrganization` trait for automatic scoping +- `OrganizationScope` provides global filtering +- Use `current_organization_id()` helper for context + +### State Machine Pattern +- Shipments use `spatie/laravel-model-states` +- States: Pending → Booked → Dispatched → AtPickup → InTransit → AtDelivery → Delivered +- State transitions trigger events for side effects + +### Frontend Structure +- React + TypeScript with Inertia.js for SPA-like experience +- Components organized by domain in `resources/js/Components/` +- UI components in `resources/js/Components/ui/` +- Pages in `resources/js/Pages/` + +### Key Models & Relationships +- `Organization` - Multi-tenant container +- `Shipment` - Core business entity with state machine +- `Carrier` - Transportation providers +- `Customer` - Freight customers +- `Contact` - Polymorphic contacts system +- `Document` - Polymorphic file attachments +- `Note` - Polymorphic notes system + +## Development Patterns + +### Adding New Features +1. Create action in appropriate domain directory +2. Add enum values if needed (sync with `Permission::syncToDatabase()`) +3. Create policy for authorization +4. Add tests in corresponding test directories +5. Create frontend components following existing patterns + +### Permissions System +- Add permissions to `app/Enums/Permission.php` +- Include entry in `label()` method +- Create migration calling `App\Enums\Permission::syncToDatabase()` + +### Event-Driven Updates +- Use event bus for real-time updates between components +- Emit events: `emit('event-name-' + id)` +- Subscribe: `subscribe('event-name-' + id, callback)` + +### Organization Defaults +- Modify `CreateOrUpdateOrganizationDefaults` action +- Consider both migration for existing orgs and action updates for new ones + +## Database & Storage + +### Database +- Uses SQLite for development, PostgreSQL for production +- Migrations in `database/migrations/` +- Seeders for test data in `database/seeders/` + +### File Storage +- Supports both local and S3 storage +- Configured via `FILESYSTEM_DISK` environment variable +- Uses polymorphic `Document` model for file attachments + +## Testing + +### Test Structure +- Unit tests in `tests/Unit/` +- Feature tests in `tests/Feature/` +- Uses Pest testing framework +- Factory classes for model creation + +### Test Users +Available via `sail artisan dev:refresh`: +- `admin@test.com` / `password` (admin) +- `user@test.com` / `password` (regular user) + +## Key Dependencies + +### Backend +- `lorisleiva/laravel-actions` - Business logic actions +- `spatie/laravel-model-states` - State machine +- `spatie/laravel-permission` - Authorization +- `inertiajs/inertia-laravel` - Frontend bridge +- `laravel/cashier` - Subscription billing + +### Frontend +- `@inertiajs/react` - Inertia.js React adapter +- `@tanstack/react-table` - Data tables +- `react-hook-form` - Form management +- `@radix-ui/*` - UI components +- `tailwindcss` - Styling + +## Code Style & Standards + +### PHP +- Follow PSR-12 coding standards +- Use PHP 8.2+ features including enums +- Type hints required for all methods +- PHPStan level 5 static analysis + +### TypeScript/React +- Strict TypeScript configuration +- Props interfaces for all components +- Use React hooks patterns +- ESLint + Prettier for code formatting + +## Troubleshooting + +### Common Issues +- Run `sail artisan storage:link` if file uploads fail +- Check organization context if data not appearing +- Verify permissions if authorization fails +- Use event bus for component updates, not direct prop passing + +### Development Environment +- All services run via Docker Compose +- Access application at `http://localhost` +- Mailpit at `http://localhost:8025` for email testing +- Database accessible via standard Laravel tools \ No newline at end of file diff --git a/_ide_helper_actions.php b/_ide_helper_actions.php index 927893ce..9efbf2b5 100644 --- a/_ide_helper_actions.php +++ b/_ide_helper_actions.php @@ -116,6 +116,20 @@ class FmcsaDOTLookup class FmcsaNameLookup { } +/** + * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Carriers\Carrier $carrier) + * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Carriers\Carrier $carrier) + * @method static \Illuminate\Foundation\Bus\PendingDispatch dispatch(\App\Models\Carriers\Carrier $carrier) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchIf(bool $boolean, \App\Models\Carriers\Carrier $carrier) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchUnless(bool $boolean, \App\Models\Carriers\Carrier $carrier) + * @method static dispatchSync(\App\Models\Carriers\Carrier $carrier) + * @method static dispatchNow(\App\Models\Carriers\Carrier $carrier) + * @method static dispatchAfterResponse(\App\Models\Carriers\Carrier $carrier) + * @method static mixed run(\App\Models\Carriers\Carrier $carrier) + */ +class GetCarrierAuditHistory +{ +} /** * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Carriers\Carrier $carrier, ?string $name = null, ?string $mc_number = null, ?string $dot_number = null, ?int $physical_location_id = null, ?string $contact_email = null, ?string $contact_phone = null) * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Carriers\Carrier $carrier, ?string $name = null, ?string $mc_number = null, ?string $dot_number = null, ?int $physical_location_id = null, ?string $contact_email = null, ?string $contact_phone = null) diff --git a/app/Actions/Audit/GetAuditLinkedData.php b/app/Actions/Audit/GetAuditLinkedData.php new file mode 100644 index 00000000..b5fa21b8 --- /dev/null +++ b/app/Actions/Audit/GetAuditLinkedData.php @@ -0,0 +1,188 @@ +getModel($type, $id); + + if (!$model) { + throw new \Exception('Record not found'); + } + + return [ + 'id' => $model->id, + 'type' => $this->getDisplayType($type), + 'title' => $this->getDisplayTitle($model, $type), + 'data' => $this->getDisplayData($model, $type), + 'view_url' => $this->getViewUrl($model, $type), + ]; + } + + public function asController(ActionRequest $request, string $type, int $id) + { + try { + $data = $this->handle($type, $id); + return response()->json($data); + } catch (\Exception $e) { + return response()->json(['error' => $e->getMessage()], 404); + } + } + + public function authorize(ActionRequest $request): bool + { + // Basic authorization - user must be logged in + // Individual models can have more specific permissions if needed + return $request->user() !== null; + } + + private function getModel(string $type, int $id): ?Model + { + return match ($type) { + 'location' => Location::find($id), + 'contact' => Contact::find($id), + 'carrier' => Carrier::find($id), + 'customer' => Customer::find($id), + 'user' => User::find($id), + default => null, + }; + } + + private function getDisplayType(string $type): string + { + return match ($type) { + 'location' => 'Location', + 'contact' => 'Contact', + 'carrier' => 'Carrier', + 'customer' => 'Customer', + 'user' => 'User', + default => ucfirst($type), + }; + } + + private function getDisplayTitle(Model $model, string $type): string + { + return match ($type) { + 'location' => $this->formatLocationTitle($model), + 'contact' => $model->name ?? 'Contact #' . $model->id, + 'carrier' => $model->name ?? 'Carrier #' . $model->id, + 'customer' => $model->name ?? 'Customer #' . $model->id, + 'user' => $model->name ?? 'User #' . $model->id, + default => ucfirst($type) . ' #' . $model->id, + }; + } + + private function formatLocationTitle(Model $location): string + { + $parts = array_filter([ + $location->name, + $location->address_line_1, + $location->address_city, + $location->address_state, + ]); + + return implode(', ', $parts) ?: 'Location #' . $location->id; + } + + private function getDisplayData(Model $model, string $type): array + { + return match ($type) { + 'location' => $this->getLocationData($model), + 'contact' => $this->getContactData($model), + 'carrier' => $this->getCarrierData($model), + 'customer' => $this->getCustomerData($model), + 'user' => $this->getUserData($model), + default => $model->toArray(), + }; + } + + private function getLocationData(Model $location): array + { + return [ + 'name' => $location->name, + 'address_line_1' => $location->address_line_1, + 'address_line_2' => $location->address_line_2, + 'city' => $location->address_city, + 'state' => $location->address_state, + 'zipcode' => $location->address_zipcode, + 'country' => $location->address_country, + 'phone' => $location->phone, + 'created_at' => $location->created_at?->format('M j, Y g:i A'), + ]; + } + + private function getContactData(Model $contact): array + { + return [ + 'name' => $contact->name, + 'email' => $contact->email, + 'phone' => $contact->phone, + 'title' => $contact->title, + 'notes' => $contact->notes, + 'created_at' => $contact->created_at?->format('M j, Y g:i A'), + ]; + } + + private function getCarrierData(Model $carrier): array + { + return [ + 'name' => $carrier->name, + 'mc_number' => $carrier->mc_number, + 'dot_number' => $carrier->dot_number, + 'contact_email' => $carrier->contact_email, + 'contact_phone' => $carrier->contact_phone, + 'billing_email' => $carrier->billing_email, + 'billing_phone' => $carrier->billing_phone, + 'created_at' => $carrier->created_at?->format('M j, Y g:i A'), + ]; + } + + private function getCustomerData(Model $customer): array + { + return [ + 'name' => $customer->name, + 'dba_name' => $customer->dba_name, + 'net_pay_days' => $customer->net_pay_days, + 'invoice_number_schema' => $customer->invoice_number_schema, + 'created_at' => $customer->created_at?->format('M j, Y g:i A'), + ]; + } + + private function getUserData(Model $user): array + { + return [ + 'name' => $user->name, + 'email' => $user->email, + 'created_at' => $user->created_at?->format('M j, Y g:i A'), + ]; + } + + private function getViewUrl(Model $model, string $type): ?string + { + try { + return match ($type) { + 'carrier' => route('carriers.show', $model->id), + 'customer' => route('customers.show', $model->id), + 'location' => null, // Locations don't have individual view pages + 'contact' => null, // Contacts don't have individual view pages + 'user' => null, // Users don't have individual view pages typically + default => null, + }; + } catch (\Exception $e) { + return null; + } + } +} \ No newline at end of file diff --git a/app/Actions/Carriers/GetCarrierAuditHistory.php b/app/Actions/Carriers/GetCarrierAuditHistory.php new file mode 100644 index 00000000..863c9aea --- /dev/null +++ b/app/Actions/Carriers/GetCarrierAuditHistory.php @@ -0,0 +1,96 @@ +audits() + ->with('user') + ->orderBy('created_at', 'desc') + ->get() + ->map(function (Audit $audit) { + return [ + 'id' => $audit->id, + 'event' => $audit->event, + 'user' => $audit->user ? [ + 'id' => $audit->user->id, + 'name' => $audit->user->name, + 'email' => $audit->user->email, + ] : null, + 'old_values' => $audit->old_values ?? [], + 'new_values' => $audit->new_values ?? [], + 'url' => $audit->url, + 'ip_address' => $audit->ip_address, + 'user_agent' => $audit->user_agent, + 'created_at' => $audit->created_at, + 'created_at_human' => $audit->created_at->diffForHumans(), + 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? []), + ]; + }); + } + + public function asController(ActionRequest $request, Carrier $carrier) + { + $audits = $this->handle($carrier); + return $this->jsonResponse($audits); + } + + public function jsonResponse($audits) + { + return response()->json([ + 'audits' => $audits, + ]); + } + + public function authorize(ActionRequest $request): bool + { + return $request->user()->can(\App\Enums\Permission::CARRIER_VIEW); + } + + private function formatChanges(array $oldValues, array $newValues): array + { + $changes = []; + $allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues))); + + foreach ($allKeys as $key) { + $oldValue = $oldValues[$key] ?? null; + $newValue = $newValues[$key] ?? null; + + if ($oldValue !== $newValue) { + $changes[] = [ + 'field' => $this->formatFieldName($key), + 'field_name' => $key, + 'old_value' => $oldValue, + 'new_value' => $newValue, + ]; + } + } + + return $changes; + } + + private function formatFieldName(string $field): string + { + return match ($field) { + 'mc_number' => 'MC Number', + 'dot_number' => 'DOT Number', + 'contact_email' => 'Contact Email', + 'contact_phone' => 'Contact Phone', + 'billing_email' => 'Billing Email', + 'billing_phone' => 'Billing Phone', + 'physical_location_id' => 'Physical Location', + 'billing_location_id' => 'Billing Location', + 'organization_id' => 'Organization', + default => ucwords(str_replace('_', ' ', $field)), + }; + } +} \ No newline at end of file diff --git a/app/Actions/Customers/GetCustomerAuditHistory.php b/app/Actions/Customers/GetCustomerAuditHistory.php new file mode 100644 index 00000000..12c53369 --- /dev/null +++ b/app/Actions/Customers/GetCustomerAuditHistory.php @@ -0,0 +1,93 @@ +audits() + ->with('user') + ->orderBy('created_at', 'desc') + ->get() + ->map(function (Audit $audit) { + return [ + 'id' => $audit->id, + 'event' => $audit->event, + 'user' => $audit->user ? [ + 'id' => $audit->user->id, + 'name' => $audit->user->name, + 'email' => $audit->user->email, + ] : null, + 'old_values' => $audit->old_values ?? [], + 'new_values' => $audit->new_values ?? [], + 'url' => $audit->url, + 'ip_address' => $audit->ip_address, + 'user_agent' => $audit->user_agent, + 'created_at' => $audit->created_at, + 'created_at_human' => $audit->created_at->diffForHumans(), + 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? []), + ]; + }); + } + + public function asController(ActionRequest $request, Customer $customer) + { + $audits = $this->handle($customer); + return $this->jsonResponse($audits); + } + + public function jsonResponse($audits) + { + return response()->json([ + 'audits' => $audits, + ]); + } + + public function authorize(ActionRequest $request): bool + { + return $request->user()->can(\App\Enums\Permission::CUSTOMER_VIEW); + } + + private function formatChanges(array $oldValues, array $newValues): array + { + $changes = []; + $allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues))); + + foreach ($allKeys as $key) { + $oldValue = $oldValues[$key] ?? null; + $newValue = $newValues[$key] ?? null; + + if ($oldValue !== $newValue) { + $changes[] = [ + 'field' => $this->formatFieldName($key), + 'field_name' => $key, + 'old_value' => $oldValue, + 'new_value' => $newValue, + ]; + } + } + + return $changes; + } + + private function formatFieldName(string $field): string + { + return match ($field) { + 'net_pay_days' => 'Net Pay Days', + 'billing_location_id' => 'Billing Location', + 'dba_name' => 'DBA Name', + 'invoice_number_schema' => 'Invoice Number Schema', + 'billing_contact_id' => 'Billing Contact', + 'organization_id' => 'Organization', + default => ucwords(str_replace('_', ' ', $field)), + }; + } +} \ No newline at end of file diff --git a/app/Models/Carriers/Carrier.php b/app/Models/Carriers/Carrier.php index 37bc583f..20538d2c 100644 --- a/app/Models/Carriers/Carrier.php +++ b/app/Models/Carriers/Carrier.php @@ -14,10 +14,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Laravel\Scout\Searchable; +use OwenIt\Auditing\Contracts\Auditable; -class Carrier extends Model +class Carrier extends Model implements Auditable { use HasFactory, HasOrganization, Searchable, HasContacts, HasDocuments, HasAliases; + use \OwenIt\Auditing\Auditable; protected $fillable = [ 'organization_id', diff --git a/app/Models/Customers/Customer.php b/app/Models/Customers/Customer.php index 43aa786f..c6e67823 100644 --- a/app/Models/Customers/Customer.php +++ b/app/Models/Customers/Customer.php @@ -13,10 +13,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; +use OwenIt\Auditing\Contracts\Auditable; -class Customer extends Model +class Customer extends Model implements Auditable { use HasFactory, HasOrganization, Searchable, HasNotes, HasContacts, HasDocuments, HasAliases; + use \OwenIt\Auditing\Auditable; protected $fillable = [ 'organization_id', diff --git a/composer.json b/composer.json index 30e80a60..733da73c 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "league/flysystem-aws-s3-v3": "^3.29", "loadpartner/fmcsa-safer-api": "^1.0", "lorisleiva/laravel-actions": "^2.9", + "owen-it/laravel-auditing": "^14.0", "propaganistas/laravel-phone": "^5.3", "spatie/laravel-model-states": "^2.11", "spatie/laravel-permission": "^6", diff --git a/composer.lock b/composer.lock index 4c631f00..b98315cb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "feb3e249d715ae6a97af26e9111406b3", + "content-hash": "c6174ea261433086a25a1abccc8bb80a", "packages": [ { "name": "amphp/amp", @@ -4777,6 +4777,90 @@ ], "time": "2025-05-08T08:14:37+00:00" }, + { + "name": "owen-it/laravel-auditing", + "version": "v14.0.0", + "source": { + "type": "git", + "url": "https://github.com/owen-it/laravel-auditing.git", + "reference": "f92602d1b3f53df29ddd577290e9d735ea707c53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/owen-it/laravel-auditing/zipball/f92602d1b3f53df29ddd577290e9d735ea707c53", + "reference": "f92602d1b3f53df29ddd577290e9d735ea707c53", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/filesystem": "^11.0|^12.0", + "php": "^8.2" + }, + "require-dev": { + "mockery/mockery": "^1.5.1", + "orchestra/testbench": "^9.0|^10.0", + "phpunit/phpunit": "^11.0" + }, + "type": "package", + "extra": { + "laravel": { + "providers": [ + "OwenIt\\Auditing\\AuditingServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "v14-dev" + } + }, + "autoload": { + "psr-4": { + "OwenIt\\Auditing\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Antério Vieira", + "email": "anteriovieira@gmail.com" + }, + { + "name": "Raphael França", + "email": "raphaelfrancabsb@gmail.com" + }, + { + "name": "Morten D. Hansen", + "email": "morten@visia.dk" + } + ], + "description": "Audit changes of your Eloquent models in Laravel", + "homepage": "https://laravel-auditing.com", + "keywords": [ + "Accountability", + "Audit", + "auditing", + "changes", + "eloquent", + "history", + "laravel", + "log", + "logging", + "lumen", + "observer", + "record", + "revision", + "tracking" + ], + "support": { + "issues": "https://github.com/owen-it/laravel-auditing/issues", + "source": "https://github.com/owen-it/laravel-auditing" + }, + "time": "2025-02-26T16:40:54+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.3", diff --git a/config/audit.php b/config/audit.php new file mode 100644 index 00000000..9c94d549 --- /dev/null +++ b/config/audit.php @@ -0,0 +1,198 @@ + env('AUDITING_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Audit Implementation + |-------------------------------------------------------------------------- + | + | Define which Audit model implementation should be used. + | + */ + + 'implementation' => OwenIt\Auditing\Models\Audit::class, + + /* + |-------------------------------------------------------------------------- + | User Morph prefix & Guards + |-------------------------------------------------------------------------- + | + | Define the morph prefix and authentication guards for the User resolver. + | + */ + + 'user' => [ + 'morph_prefix' => 'user', + 'guards' => [ + 'web', + 'api', + ], + 'resolver' => OwenIt\Auditing\Resolvers\UserResolver::class, + ], + + /* + |-------------------------------------------------------------------------- + | Audit Resolvers + |-------------------------------------------------------------------------- + | + | Define the IP Address, User Agent and URL resolver implementations. + | + */ + 'resolvers' => [ + 'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class, + 'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class, + 'url' => OwenIt\Auditing\Resolvers\UrlResolver::class, + ], + + /* + |-------------------------------------------------------------------------- + | Audit Events + |-------------------------------------------------------------------------- + | + | The Eloquent events that trigger an Audit. + | + */ + + 'events' => [ + 'created', + 'updated', + 'deleted', + 'restored', + ], + + /* + |-------------------------------------------------------------------------- + | Strict Mode + |-------------------------------------------------------------------------- + | + | Enable the strict mode when auditing? + | + */ + + 'strict' => false, + + /* + |-------------------------------------------------------------------------- + | Global exclude + |-------------------------------------------------------------------------- + | + | Have something you always want to exclude by default? - add it here. + | Note that this is overwritten (not merged) with local exclude + | + */ + + 'exclude' => [], + + /* + |-------------------------------------------------------------------------- + | Empty Values + |-------------------------------------------------------------------------- + | + | Should Audit records be stored when the recorded old_values & new_values + | are both empty? + | + | Some events may be empty on purpose. Use allowed_empty_values to exclude + | those from the empty values check. For example when auditing + | model retrieved events which will never have new and old values. + | + | + */ + + 'empty_values' => true, + 'allowed_empty_values' => [ + 'retrieved', + ], + + /* + |-------------------------------------------------------------------------- + | Allowed Array Values + |-------------------------------------------------------------------------- + | + | Should the array values be audited? + | + | By default, array values are not allowed. This is to prevent performance + | issues when storing large amounts of data. You can override this by + | setting allow_array_values to true. + */ + 'allowed_array_values' => false, + + /* + |-------------------------------------------------------------------------- + | Audit Timestamps + |-------------------------------------------------------------------------- + | + | Should the created_at, updated_at and deleted_at timestamps be audited? + | + */ + + 'timestamps' => false, + + /* + |-------------------------------------------------------------------------- + | Audit Threshold + |-------------------------------------------------------------------------- + | + | Specify a threshold for the amount of Audit records a model can have. + | Zero means no limit. + | + */ + + 'threshold' => 0, + + /* + |-------------------------------------------------------------------------- + | Audit Driver + |-------------------------------------------------------------------------- + | + | The default audit driver used to keep track of changes. + | + */ + + 'driver' => 'database', + + /* + |-------------------------------------------------------------------------- + | Audit Driver Configurations + |-------------------------------------------------------------------------- + | + | Available audit drivers and respective configurations. + | + */ + + 'drivers' => [ + 'database' => [ + 'table' => 'audits', + 'connection' => null, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Audit Queue Configurations + |-------------------------------------------------------------------------- + | + | Available audit queue configurations. + | + */ + + 'queue' => [ + 'enable' => false, + 'connection' => 'sync', + 'queue' => 'default', + 'delay' => 0, + ], + + /* + |-------------------------------------------------------------------------- + | Audit Console + |-------------------------------------------------------------------------- + | + | Whether console events should be audited (eg. php artisan db:seed). + | + */ + + 'console' => false, +]; diff --git a/database/migrations/2025_07_10_004424_create_audits_table.php b/database/migrations/2025_07_10_004424_create_audits_table.php new file mode 100644 index 00000000..7ce54a6d --- /dev/null +++ b/database/migrations/2025_07_10_004424_create_audits_table.php @@ -0,0 +1,48 @@ +create($table, function (Blueprint $table) { + + $morphPrefix = config('audit.user.morph_prefix', 'user'); + + $table->bigIncrements('id'); + $table->string($morphPrefix . '_type')->nullable(); + $table->unsignedBigInteger($morphPrefix . '_id')->nullable(); + $table->string('event'); + $table->morphs('auditable'); + $table->text('old_values')->nullable(); + $table->text('new_values')->nullable(); + $table->text('url')->nullable(); + $table->ipAddress('ip_address')->nullable(); + $table->string('user_agent', 1023)->nullable(); + $table->string('tags')->nullable(); + $table->timestamps(); + + $table->index([$morphPrefix . '_id', $morphPrefix . '_type']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $connection = config('audit.drivers.database.connection', config('database.default')); + $table = config('audit.drivers.database.table', 'audits'); + + Schema::connection($connection)->drop($table); + } +}; diff --git a/resources/js/Components/AppSidebar.tsx b/resources/js/Components/AppSidebar.tsx index 612d39ba..4da4d8e5 100644 --- a/resources/js/Components/AppSidebar.tsx +++ b/resources/js/Components/AppSidebar.tsx @@ -132,147 +132,147 @@ export function AppSidebar({ ...props }: React.ComponentProps) { - {(permissions?.ORGANIZATION_MANAGER || - permissions?.ORGANIZATION_MANAGE_USERS) && ( - - - - - - Organization - - - - - - - - Users - - - - - Roles - - - {permissions?.INTEGRATION_SETTINGS_EDIT && ( + {(permissions?.ORGANIZATION_MANAGER || + permissions?.ORGANIZATION_MANAGE_USERS) && ( + + + + + + Organization + + + + + - Integration Settings - - - )} - {permissions?.ORGANIZATION_MANAGER && ( - - - Document Templates + Users - )} - {permissions?.ORGANIZATION_MANAGER && ( - Settings + Roles - )} - {permissions?.ORGANIZATION_BILLING && - config?.enable_billing && ( + {permissions?.INTEGRATION_SETTINGS_EDIT && ( - Billing + Integration Settings )} - - - - - )} - + + Document Templates + + + )} + {permissions?.ORGANIZATION_MANAGER && ( + + + Settings + + + )} + {permissions?.ORGANIZATION_BILLING && + config?.enable_billing && ( + + + Billing + + + )} + + + + + )} + setIsFeedbackModalOpen(true)} > diff --git a/resources/js/Components/Audit/AuditFieldValue.tsx b/resources/js/Components/Audit/AuditFieldValue.tsx new file mode 100644 index 00000000..08054156 --- /dev/null +++ b/resources/js/Components/Audit/AuditFieldValue.tsx @@ -0,0 +1,77 @@ +import { Button } from '@/Components/ui/button'; +import { ExternalLink } from 'lucide-react'; +import { useState } from 'react'; +import AuditLinkedDataModal from './AuditLinkedDataModal'; + +interface AuditFieldValueProps { + fieldName: string; + value: unknown; + className?: string; +} + +// Map of field names to their corresponding model types +const FOREIGN_KEY_MAPPINGS: Record = { + 'billing_location_id': 'location', + 'physical_location_id': 'location', + 'location_id': 'location', + 'billing_contact_id': 'contact', + 'contact_id': 'contact', + 'user_id': 'user', + 'created_by': 'user', + 'updated_by': 'user', + 'carrier_id': 'carrier', + 'customer_id': 'customer', +}; + +export default function AuditFieldValue({ + fieldName, + value, + className = '', +}: AuditFieldValueProps) { + const [modalOpen, setModalOpen] = useState(false); + + const formatValue = (value: unknown): string => { + if (value === null || value === undefined) { + return 'No value'; + } + if (typeof value === 'boolean') { + return value ? 'Yes' : 'No'; + } + if (typeof value === 'object') { + return JSON.stringify(value); + } + return String(value); + }; + + // Check if this field is a foreign key + const modelType = FOREIGN_KEY_MAPPINGS[fieldName.toLowerCase()]; + const isForeignKey = modelType && value && String(value).match(/^\d+$/); + + if (isForeignKey) { + return ( + <> +
+ {formatValue(value)} + +
+ + + + ); + } + + return {formatValue(value)}; +} \ No newline at end of file diff --git a/resources/js/Components/Audit/AuditLinkedDataModal.tsx b/resources/js/Components/Audit/AuditLinkedDataModal.tsx new file mode 100644 index 00000000..64bc9356 --- /dev/null +++ b/resources/js/Components/Audit/AuditLinkedDataModal.tsx @@ -0,0 +1,172 @@ +import { Button } from '@/Components/ui/button'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/Components/ui/dialog'; +import { Skeleton } from '@/Components/ui/skeleton'; +import { ExternalLink, X } from 'lucide-react'; +import { useEffect, useState } from 'react'; + +interface LinkedData { + id: number; + type: string; + title: string; + data: Record; + view_url?: string; +} + +interface AuditLinkedDataModalProps { + open: boolean; + onOpenChange: (open: boolean) => void; + modelType: string; + modelId: string | number; +} + +export default function AuditLinkedDataModal({ + open, + onOpenChange, + modelType, + modelId, +}: AuditLinkedDataModalProps) { + const [linkedData, setLinkedData] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + if (open && modelId && modelType) { + fetchLinkedData(); + } + }, [open, modelId, modelType]); + + const fetchLinkedData = async () => { + try { + setLoading(true); + setError(null); + + const response = await fetch( + route('audit.linked-data', { + type: modelType, + id: modelId, + }), + ); + + if (!response.ok) { + throw new Error('Failed to fetch linked data'); + } + + const data = await response.json(); + setLinkedData(data); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + const formatFieldName = (key: string): string => { + return key + .split('_') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + }; + + const formatValue = (value: unknown): string => { + if (value === null || value === undefined) { + return '—'; + } + if (typeof value === 'boolean') { + return value ? 'Yes' : 'No'; + } + if (typeof value === 'object') { + return JSON.stringify(value); + } + return String(value); + }; + + const handleViewRecord = () => { + if (linkedData?.view_url) { + window.open(linkedData.view_url, '_blank'); + } + }; + + return ( + + + + + + {loading + ? 'Loading...' + : linkedData?.title || 'Linked Data'} + +
+ {linkedData?.view_url && ( + + )} +
+
+
+ +
+ {loading && ( +
+ + + + +
+ )} + + {error && ( +
+
Error loading data
+
{error}
+
+ )} + + {linkedData && !loading && !error && ( +
+
+
+ {linkedData.type} +
+
+ {linkedData.title} +
+
+ +
+ {Object.entries(linkedData.data) + .filter(([key]) => key !== 'id') + .map(([key, value]) => ( +
+
+ {formatFieldName(key)} +
+
+ {formatValue(value)} +
+
+ ))} +
+
+ )} +
+
+
+ ); +} \ No newline at end of file diff --git a/resources/js/Components/Audit/AuditTable.tsx b/resources/js/Components/Audit/AuditTable.tsx new file mode 100644 index 00000000..f2d5b575 --- /dev/null +++ b/resources/js/Components/Audit/AuditTable.tsx @@ -0,0 +1,451 @@ +import { Badge } from '@/Components/ui/badge'; +import { Button } from '@/Components/ui/button'; +import { Card, CardContent } from '@/Components/ui/card'; +import { Input } from '@/Components/ui/input'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/Components/ui/select'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/Components/ui/table'; +import { Download, Filter, Search } from 'lucide-react'; +import { useMemo, useState } from 'react'; +import AuditFieldValue from './AuditFieldValue'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface AuditTableProps { + audits: AuditEntry[]; + loading?: boolean; +} + +export default function AuditTable({ audits, loading }: AuditTableProps) { + const [searchTerm, setSearchTerm] = useState(''); + const [eventFilter, setEventFilter] = useState('all'); + const [userFilter, setUserFilter] = useState('all'); + const [sortField, setSortField] = useState<'created_at' | 'event' | 'user'>( + 'created_at', + ); + const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); + + // Get unique users for filter + const uniqueUsers = useMemo(() => { + const users = audits + .filter((audit) => audit.user) + .map((audit) => audit.user!) + .filter( + (user, index, self) => + self.findIndex((u) => u.id === user.id) === index, + ); + return users; + }, [audits]); + + // Filter and sort audits + const filteredAndSortedAudits = useMemo(() => { + const filtered = audits.filter((audit) => { + // Search filter + if (searchTerm) { + const searchLower = searchTerm.toLowerCase(); + const matchesUser = + audit.user?.name.toLowerCase().includes(searchLower) || + audit.user?.email.toLowerCase().includes(searchLower); + const matchesChanges = audit.changes.some( + (change) => + change.field.toLowerCase().includes(searchLower) || + String(change.old_value) + .toLowerCase() + .includes(searchLower) || + String(change.new_value) + .toLowerCase() + .includes(searchLower), + ); + if (!matchesUser && !matchesChanges) return false; + } + + // Event filter + if (eventFilter !== 'all' && audit.event !== eventFilter) + return false; + + // User filter + if ( + userFilter !== 'all' && + audit.user?.id.toString() !== userFilter + ) + return false; + + return true; + }); + + // Sort + filtered.sort((a, b) => { + let aValue: string | number; + let bValue: string | number; + + switch (sortField) { + case 'created_at': + aValue = new Date(a.created_at).getTime(); + bValue = new Date(b.created_at).getTime(); + break; + case 'event': + aValue = a.event; + bValue = b.event; + break; + case 'user': + aValue = a.user?.name || ''; + bValue = b.user?.name || ''; + break; + default: + aValue = new Date(a.created_at).getTime(); + bValue = new Date(b.created_at).getTime(); + } + + if (sortDirection === 'asc') { + return aValue > bValue ? 1 : -1; + } else { + return aValue < bValue ? 1 : -1; + } + }); + + return filtered; + }, [audits, searchTerm, eventFilter, userFilter, sortField, sortDirection]); + + const handleSort = (field: 'created_at' | 'event' | 'user') => { + if (sortField === field) { + setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); + } else { + setSortField(field); + setSortDirection('desc'); + } + }; + + const getEventBadgeVariant = (event: string) => { + switch (event) { + case 'created': + return 'default'; + case 'updated': + return 'secondary'; + case 'deleted': + return 'destructive'; + default: + return 'outline'; + } + }; + + const formatValue = (value: unknown): string => { + if (value === null || value === undefined) { + return 'No value'; + } + if (typeof value === 'boolean') { + return value ? 'Yes' : 'No'; + } + if (typeof value === 'object') { + return JSON.stringify(value); + } + return String(value); + }; + + const exportToCsv = () => { + const headers = ['Date', 'Event', 'User', 'Changes']; + const csvData = filteredAndSortedAudits.map((audit) => [ + new Date(audit.created_at).toLocaleString(), + audit.event, + audit.user?.name || 'System', + audit.changes + .map( + (c) => + `${c.field}: ${formatValue(c.old_value)} → ${formatValue(c.new_value)}`, + ) + .join('; '), + ]); + + const csvContent = [headers, ...csvData] + .map((row) => row.map((field) => `"${field}"`).join(',')) + .join('\n'); + + const blob = new Blob([csvContent], { type: 'text/csv' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `audit-log-${new Date().toISOString().split('T')[0]}.csv`; + a.click(); + window.URL.revokeObjectURL(url); + }; + + if (loading) { + return ( + + +
+
+
+ {[...Array(5)].map((_, i) => ( +
+ ))} +
+
+
+
+ ); + } + + return ( + + + {/* Filters and Actions */} +
+
+
+ + Filters +
+ +
+ +
+ {/* Search */} +
+ + setSearchTerm(e.target.value)} + className="pl-10" + /> +
+ + {/* Event Filter */} + + + {/* User Filter */} + + + {/* Results count */} +
+ {filteredAndSortedAudits.length} of {audits.length}{' '} + entries +
+
+
+ + {/* Table */} +
+ + + + handleSort('created_at')} + > +
+ Date/Time + {sortField === 'created_at' && ( + + {sortDirection === 'asc' + ? '↑' + : '↓'} + + )} +
+
+ handleSort('event')} + > +
+ Event + {sortField === 'event' && ( + + {sortDirection === 'asc' + ? '↑' + : '↓'} + + )} +
+
+ handleSort('user')} + > +
+ User + {sortField === 'user' && ( + + {sortDirection === 'asc' + ? '↑' + : '↓'} + + )} +
+
+ Changes +
+
+ + {filteredAndSortedAudits.length === 0 ? ( + + + {audits.length === 0 + ? 'No audit records found' + : 'No records match your filters'} + + + ) : ( + filteredAndSortedAudits.map((audit) => ( + + +
+
+ {new Date( + audit.created_at, + ).toLocaleDateString()} +
+
+ {new Date( + audit.created_at, + ).toLocaleTimeString()} +
+
+
+ + + {audit.event} + + + + {audit.user ? ( +
+
+ {audit.user.name} +
+
+ {audit.user.email} +
+
+ ) : ( + + System + + )} +
+ +
+ {audit.changes.length === 0 ? ( + + No changes + + ) : ( + audit.changes.map((change, changeIndex) => ( +
+
+ {change.field} +
+
+ + + + + + + +
+
+ )) + )} +
+
+
+ )) + )} +
+
+
+
+
+ ); +} diff --git a/resources/js/Components/Audit/AuditTimeline.tsx b/resources/js/Components/Audit/AuditTimeline.tsx new file mode 100644 index 00000000..fc7bf1e1 --- /dev/null +++ b/resources/js/Components/Audit/AuditTimeline.tsx @@ -0,0 +1,281 @@ +import { Badge } from '@/Components/ui/badge'; +import { Card, CardContent } from '@/Components/ui/card'; +import { cn } from '@/lib/utils'; +import { Calendar, Clock, Edit, Plus, Trash2, User } from 'lucide-react'; +import { useState } from 'react'; +import AuditFieldValue from './AuditFieldValue'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface AuditTimelineProps { + audits: AuditEntry[]; + loading?: boolean; +} + +export default function AuditTimeline({ audits, loading }: AuditTimelineProps) { + const [expandedEntries, setExpandedEntries] = useState>( + new Set(), + ); + + const toggleExpanded = (auditId: number) => { + const newExpanded = new Set(expandedEntries); + if (newExpanded.has(auditId)) { + newExpanded.delete(auditId); + } else { + newExpanded.add(auditId); + } + setExpandedEntries(newExpanded); + }; + + const getEventIcon = (event: string) => { + switch (event) { + case 'created': + return ; + case 'updated': + return ; + case 'deleted': + return ; + default: + return ; + } + }; + + const getEventColor = (event: string) => { + switch (event) { + case 'created': + return 'text-green-600 bg-green-100'; + case 'updated': + return 'text-blue-600 bg-blue-100'; + case 'deleted': + return 'text-red-600 bg-red-100'; + default: + return 'text-gray-600 bg-gray-100'; + } + }; + + const getEventTitle = (event: string) => { + switch (event) { + case 'created': + return 'Created'; + case 'updated': + return 'Updated'; + case 'deleted': + return 'Deleted'; + default: + return 'Modified'; + } + }; + + const formatValue = (value: unknown): string => { + if (value === null || value === undefined) { + return 'No value'; + } + if (typeof value === 'boolean') { + return value ? 'Yes' : 'No'; + } + if (typeof value === 'object') { + return JSON.stringify(value); + } + return String(value); + }; + + if (loading) { + return ( +
+ {[...Array(3)].map((_, i) => ( + + +
+
+
+
+
+
+
+
+
+ ))} +
+ ); + } + + if (audits.length === 0) { + return ( +
+ +

No audit history available

+
+ ); + } + + return ( +
+ {audits.map((audit, index) => ( + + {/* Timeline line */} + {index < audits.length - 1 && ( +
+ )} + + +
+ {/* Event Icon */} +
+ {getEventIcon(audit.event)} +
+ + {/* Content */} +
+
+
+ + {getEventTitle(audit.event)} + + {audit.user && ( +
+ + {audit.user.name} +
+ )} +
+
+ + {audit.created_at_human} +
+
+ + {/* Changes Summary */} + {audit.changes.length > 0 && ( +
+

+ {audit.changes.length === 1 + ? `Modified ${audit.changes[0].field.toLowerCase()}` + : `Modified ${audit.changes.length} fields`} +

+ + {/* Quick preview for single change */} + {audit.changes.length === 1 && ( +
+ + + + + → + + + + +
+ )} +
+ )} + + {/* Expand/Collapse for details */} + {audit.changes.length > 0 && ( + + )} + + {/* Expanded Details */} + {expandedEntries.has(audit.id) && ( +
+ {audit.changes.map( + (change, changeIndex) => ( +
+
+ {change.field} +
+
+
+
+ Previous +
+
+ +
+
+
+
+ New +
+
+ +
+
+
+
+ ), + )} + + {/* Additional metadata */} +
+
+ Time:{' '} + {new Date( + audit.created_at, + ).toLocaleString()} +
+ {audit.ip_address && ( +
+ IP: {audit.ip_address} +
+ )} +
+
+ )} +
+
+
+
+ ))} +
+ ); +} diff --git a/resources/js/Components/Audit/CarrierAuditHistory.tsx b/resources/js/Components/Audit/CarrierAuditHistory.tsx new file mode 100644 index 00000000..5edd7f92 --- /dev/null +++ b/resources/js/Components/Audit/CarrierAuditHistory.tsx @@ -0,0 +1,122 @@ +import { Card, CardContent } from '@/Components/ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; +import { Carrier } from '@/types'; +import { Clock, Table } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import AuditTable from './AuditTable'; +import AuditTimeline from './AuditTimeline'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface CarrierAuditHistoryProps { + carrier: Carrier; +} + +export default function CarrierAuditHistory({ + carrier, +}: CarrierAuditHistoryProps) { + const [audits, setAudits] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [activeTab, setActiveTab] = useState('timeline'); + + useEffect(() => { + const fetchAudits = async () => { + try { + setLoading(true); + const response = await fetch( + route('carriers.audit-history', carrier.id), + ); + + if (!response.ok) { + throw new Error('Failed to fetch audit history'); + } + + const data = await response.json(); + setAudits(data.audits || []); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + if (carrier.id) { + fetchAudits(); + } + }, [carrier.id]); + + if (error) { + return ( + + +
+
+ Error loading audit history +
+
{error}
+
+
+
+ ); + } + + return ( +
+ + + + + Audit Timeline + + + + Audit Table + + + + + + + + + + + + + ); +} diff --git a/resources/js/Components/Audit/CustomerAuditHistory.tsx b/resources/js/Components/Audit/CustomerAuditHistory.tsx new file mode 100644 index 00000000..7435d92a --- /dev/null +++ b/resources/js/Components/Audit/CustomerAuditHistory.tsx @@ -0,0 +1,122 @@ +import { Card, CardContent } from '@/Components/ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; +import { Customer } from '@/types'; +import { Clock, Table } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import AuditTable from './AuditTable'; +import AuditTimeline from './AuditTimeline'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface CustomerAuditHistoryProps { + customer: Customer; +} + +export default function CustomerAuditHistory({ + customer, +}: CustomerAuditHistoryProps) { + const [audits, setAudits] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [activeTab, setActiveTab] = useState('timeline'); + + useEffect(() => { + const fetchAudits = async () => { + try { + setLoading(true); + const response = await fetch( + route('customers.audit-history', customer.id), + ); + + if (!response.ok) { + throw new Error('Failed to fetch audit history'); + } + + const data = await response.json(); + setAudits(data.audits || []); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + if (customer.id) { + fetchAudits(); + } + }, [customer.id]); + + if (error) { + return ( + + +
+
+ Error loading audit history +
+
{error}
+
+
+
+ ); + } + + return ( +
+ + + + + Audit Timeline + + +
+ Audit Table + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/resources/js/Pages/Carriers/Partials/CarrierDetails.tsx b/resources/js/Pages/Carriers/Partials/CarrierDetails.tsx index 477349d4..86792ff9 100644 --- a/resources/js/Pages/Carriers/Partials/CarrierDetails.tsx +++ b/resources/js/Pages/Carriers/Partials/CarrierDetails.tsx @@ -1,3 +1,4 @@ +import CarrierAuditHistory from '@/Components/Audit/CarrierAuditHistory'; import ContactList from '@/Components/Contacts/ContactList/ContactList'; import DocumentsList from '@/Components/Documents/DocumentsList'; import ShipmentList from '@/Components/Shipments/ShipmentList/ShipmentList'; @@ -143,6 +144,7 @@ export default function CarrierDetails({ carrier }: { carrier: Carrier }) { Shipment History SAFER + Audit History ) : ( @@ -183,6 +185,12 @@ export default function CarrierDetails({ carrier }: { carrier: Carrier }) { > SAFER + handleTabChange('audit')} + > + Audit History + )} @@ -581,6 +589,11 @@ export default function CarrierDetails({ carrier }: { carrier: Carrier }) { + + {/* Audit History Tab */} + + + ); diff --git a/resources/js/Pages/Customers/Partials/CustomerDetails.tsx b/resources/js/Pages/Customers/Partials/CustomerDetails.tsx index 4e3e923c..3c86c25a 100644 --- a/resources/js/Pages/Customers/Partials/CustomerDetails.tsx +++ b/resources/js/Pages/Customers/Partials/CustomerDetails.tsx @@ -1,3 +1,4 @@ +import CustomerAuditHistory from '@/Components/Audit/CustomerAuditHistory'; import ContactList from '@/Components/Contacts/ContactList/ContactList'; import ContactForm from '@/Components/CreateForms/ContactForm'; import LocationForm from '@/Components/CreateForms/LocationForm'; @@ -119,6 +120,7 @@ export default function CustomerDetails({ customer }: { customer: Customer }) { Shipment History + Audit History ) : ( @@ -153,6 +155,12 @@ export default function CustomerDetails({ customer }: { customer: Customer }) { > Shipment History + handleTabChange('audit')} + > + Audit History + )} @@ -605,6 +613,11 @@ export default function CustomerDetails({ customer }: { customer: Customer }) { + + {/* Audit History Tab */} + + + ); diff --git a/routes/web.php b/routes/web.php index 6381203e..04e9118c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -8,6 +8,8 @@ use App\Actions\Carriers\CreateCarrierFromSaferReport; use App\Actions\Carriers\FmcsaDOTLookup; use App\Actions\Carriers\FmcsaNameLookup; +use App\Actions\Audit\GetAuditLinkedData; +use App\Actions\Carriers\GetCarrierAuditHistory; use App\Actions\Carriers\UpdateCarrierGeneral; use App\Actions\Contacts\CreateContact; use App\Actions\Contacts\DeleteContact; @@ -16,6 +18,7 @@ use App\Actions\Customers\CreateCustomer; use App\Actions\Customers\CreateCustomerFacility; use App\Actions\Customers\DeleteCustomerFacility; +use App\Actions\Customers\GetCustomerAuditHistory; use App\Actions\Customers\UpdateCustomer; use App\Actions\Dashboard\RecentCarriersCard; use App\Actions\Dashboard\RecentShipmentsCard; @@ -185,6 +188,11 @@ Route::post('carriers', CreateCarrier::class)->name('carriers.store'); Route::get('carriers/{carrier}/bounced-loads', [CarrierController::class, 'bouncedLoads'])->name('carriers.bounced-loads'); + Route::get('carriers/{carrier}/audit-history', GetCarrierAuditHistory::class)->name('carriers.audit-history'); + + Route::get('customers/{customer}/audit-history', GetCustomerAuditHistory::class)->name('customers.audit-history'); + + Route::get('audit/linked-data/{type}/{id}', GetAuditLinkedData::class)->name('audit.linked-data'); Route::get('carriers/fmcsa/name', FmcsaNameLookup::class)->name('carriers.fmcsa.lookup.name'); Route::post('carriers/fmcsa/{carrierSaferReport}/create', CreateCarrierFromSaferReport::class)->name('carriers.fmcsa.store'); From 70fcecc4461ae28b2e99fb0a05670a39569a9a87 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Fri, 11 Jul 2025 15:40:09 -0400 Subject: [PATCH 2/7] Working audits for facilities, contacts, docs --- _ide_helper_actions.php | 44 ++++ .../Carriers/GetCarrierAuditHistory.php | 79 ++----- .../Customers/GetCustomerAuditHistory.php | 73 ++---- .../Facilities/GetFacilityAuditHistory.php | 52 +++++ app/Models/Contact.php | 4 +- app/Models/Documents/Document.php | 4 +- app/Models/Facility.php | 4 +- app/Traits/HandlesAuditHistory.php | 210 ++++++++++++++++++ .../js/Components/Audit/AuditFieldValue.tsx | 49 +++- .../Components/Audit/AuditLinkedDataModal.tsx | 16 +- resources/js/Components/Audit/AuditTable.tsx | 106 +++++++-- .../js/Components/Audit/AuditTimeline.tsx | 60 ++++- .../Components/Audit/CustomerAuditHistory.tsx | 6 +- .../Components/Audit/FacilityAuditHistory.tsx | 126 +++++++++++ .../Facilities/Partials/FacilityDetails.tsx | 13 ++ routes/web.php | 2 + 16 files changed, 680 insertions(+), 168 deletions(-) create mode 100644 app/Actions/Facilities/GetFacilityAuditHistory.php create mode 100644 app/Traits/HandlesAuditHistory.php create mode 100644 resources/js/Components/Audit/FacilityAuditHistory.tsx diff --git a/_ide_helper_actions.php b/_ide_helper_actions.php index 9efbf2b5..d004569f 100644 --- a/_ide_helper_actions.php +++ b/_ide_helper_actions.php @@ -44,6 +44,22 @@ class SavePayables class SaveReceivables { } +namespace App\Actions\Audit; + +/** + * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(string $type, int $id) + * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(string $type, int $id) + * @method static \Illuminate\Foundation\Bus\PendingDispatch dispatch(string $type, int $id) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchIf(bool $boolean, string $type, int $id) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchUnless(bool $boolean, string $type, int $id) + * @method static dispatchSync(string $type, int $id) + * @method static dispatchNow(string $type, int $id) + * @method static dispatchAfterResponse(string $type, int $id) + * @method static mixed run(string $type, int $id) + */ +class GetAuditLinkedData +{ +} namespace App\Actions\Carriers; /** @@ -262,6 +278,20 @@ class CreateCustomerFacility class DeleteCustomerFacility { } +/** + * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Customers\Customer $customer) + * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Customers\Customer $customer) + * @method static \Illuminate\Foundation\Bus\PendingDispatch dispatch(\App\Models\Customers\Customer $customer) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchIf(bool $boolean, \App\Models\Customers\Customer $customer) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchUnless(bool $boolean, \App\Models\Customers\Customer $customer) + * @method static dispatchSync(\App\Models\Customers\Customer $customer) + * @method static dispatchNow(\App\Models\Customers\Customer $customer) + * @method static dispatchAfterResponse(\App\Models\Customers\Customer $customer) + * @method static mixed run(\App\Models\Customers\Customer $customer) + */ +class GetCustomerAuditHistory +{ +} /** * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Customers\Customer $customer, ?string $name = null, ?int $net_pay_days = null, ?int $billing_location_id = null, ?string $dba_name = null, ?string $invoice_number_schema = null, ?int $billing_contact_id = null) * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Customers\Customer $customer, ?string $name = null, ?int $net_pay_days = null, ?int $billing_location_id = null, ?string $dba_name = null, ?string $invoice_number_schema = null, ?int $billing_contact_id = null) @@ -512,6 +542,20 @@ class GenerateRateConfirmation class CreateFacility { } +/** + * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Facility $facility) + * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Facility $facility) + * @method static \Illuminate\Foundation\Bus\PendingDispatch dispatch(\App\Models\Facility $facility) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchIf(bool $boolean, \App\Models\Facility $facility) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchUnless(bool $boolean, \App\Models\Facility $facility) + * @method static dispatchSync(\App\Models\Facility $facility) + * @method static dispatchNow(\App\Models\Facility $facility) + * @method static dispatchAfterResponse(\App\Models\Facility $facility) + * @method static mixed run(\App\Models\Facility $facility) + */ +class GetFacilityAuditHistory +{ +} /** * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Facility $facility, ?string $name = null, ?int $location_id = null) * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Facility $facility, ?string $name = null, ?int $location_id = null) diff --git a/app/Actions/Carriers/GetCarrierAuditHistory.php b/app/Actions/Carriers/GetCarrierAuditHistory.php index 863c9aea..f05b12b1 100644 --- a/app/Actions/Carriers/GetCarrierAuditHistory.php +++ b/app/Actions/Carriers/GetCarrierAuditHistory.php @@ -3,39 +3,20 @@ namespace App\Actions\Carriers; use App\Models\Carriers\Carrier; +use App\Models\Contact; +use App\Models\Documents\Document; +use App\Traits\HandlesAuditHistory; use Lorisleiva\Actions\ActionRequest; use Lorisleiva\Actions\Concerns\AsAction; -use OwenIt\Auditing\Models\Audit; class GetCarrierAuditHistory { - use AsAction; + use AsAction, HandlesAuditHistory; public function handle(Carrier $carrier) { - return $carrier->audits() - ->with('user') - ->orderBy('created_at', 'desc') - ->get() - ->map(function (Audit $audit) { - return [ - 'id' => $audit->id, - 'event' => $audit->event, - 'user' => $audit->user ? [ - 'id' => $audit->user->id, - 'name' => $audit->user->name, - 'email' => $audit->user->email, - ] : null, - 'old_values' => $audit->old_values ?? [], - 'new_values' => $audit->new_values ?? [], - 'url' => $audit->url, - 'ip_address' => $audit->ip_address, - 'user_agent' => $audit->user_agent, - 'created_at' => $audit->created_at, - 'created_at_human' => $audit->created_at->diffForHumans(), - 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? []), - ]; - }); + $audits = $this->getAuditHistory($carrier); + return $this->formatAuditData($audits); } public function asController(ActionRequest $request, Carrier $carrier) @@ -56,41 +37,23 @@ public function authorize(ActionRequest $request): bool return $request->user()->can(\App\Enums\Permission::CARRIER_VIEW); } - private function formatChanges(array $oldValues, array $newValues): array + protected function getModelSpecificFieldMappings(string $auditableType): array { - $changes = []; - $allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues))); - - foreach ($allKeys as $key) { - $oldValue = $oldValues[$key] ?? null; - $newValue = $newValues[$key] ?? null; - - if ($oldValue !== $newValue) { - $changes[] = [ - 'field' => $this->formatFieldName($key), - 'field_name' => $key, - 'old_value' => $oldValue, - 'new_value' => $newValue, - ]; - } + // Handle carrier-specific fields + if ($auditableType === Carrier::class) { + return [ + 'mc_number' => 'MC Number', + 'dot_number' => 'DOT Number', + 'contact_email' => 'Contact Email', + 'contact_phone' => 'Contact Phone', + 'billing_email' => 'Billing Email', + 'billing_phone' => 'Billing Phone', + 'physical_location_id' => 'Physical Location', + 'billing_location_id' => 'Billing Location', + 'organization_id' => 'Organization', + ]; } - return $changes; - } - - private function formatFieldName(string $field): string - { - return match ($field) { - 'mc_number' => 'MC Number', - 'dot_number' => 'DOT Number', - 'contact_email' => 'Contact Email', - 'contact_phone' => 'Contact Phone', - 'billing_email' => 'Billing Email', - 'billing_phone' => 'Billing Phone', - 'physical_location_id' => 'Physical Location', - 'billing_location_id' => 'Billing Location', - 'organization_id' => 'Organization', - default => ucwords(str_replace('_', ' ', $field)), - }; + return []; } } \ No newline at end of file diff --git a/app/Actions/Customers/GetCustomerAuditHistory.php b/app/Actions/Customers/GetCustomerAuditHistory.php index 12c53369..7081e8ba 100644 --- a/app/Actions/Customers/GetCustomerAuditHistory.php +++ b/app/Actions/Customers/GetCustomerAuditHistory.php @@ -2,40 +2,21 @@ namespace App\Actions\Customers; +use App\Models\Contact; use App\Models\Customers\Customer; +use App\Models\Documents\Document; +use App\Traits\HandlesAuditHistory; use Lorisleiva\Actions\ActionRequest; use Lorisleiva\Actions\Concerns\AsAction; -use OwenIt\Auditing\Models\Audit; class GetCustomerAuditHistory { - use AsAction; + use AsAction, HandlesAuditHistory; public function handle(Customer $customer) { - return $customer->audits() - ->with('user') - ->orderBy('created_at', 'desc') - ->get() - ->map(function (Audit $audit) { - return [ - 'id' => $audit->id, - 'event' => $audit->event, - 'user' => $audit->user ? [ - 'id' => $audit->user->id, - 'name' => $audit->user->name, - 'email' => $audit->user->email, - ] : null, - 'old_values' => $audit->old_values ?? [], - 'new_values' => $audit->new_values ?? [], - 'url' => $audit->url, - 'ip_address' => $audit->ip_address, - 'user_agent' => $audit->user_agent, - 'created_at' => $audit->created_at, - 'created_at_human' => $audit->created_at->diffForHumans(), - 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? []), - ]; - }); + $audits = $this->getAuditHistory($customer); + return $this->formatAuditData($audits); } public function asController(ActionRequest $request, Customer $customer) @@ -56,38 +37,20 @@ public function authorize(ActionRequest $request): bool return $request->user()->can(\App\Enums\Permission::CUSTOMER_VIEW); } - private function formatChanges(array $oldValues, array $newValues): array + protected function getModelSpecificFieldMappings(string $auditableType): array { - $changes = []; - $allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues))); - - foreach ($allKeys as $key) { - $oldValue = $oldValues[$key] ?? null; - $newValue = $newValues[$key] ?? null; - - if ($oldValue !== $newValue) { - $changes[] = [ - 'field' => $this->formatFieldName($key), - 'field_name' => $key, - 'old_value' => $oldValue, - 'new_value' => $newValue, - ]; - } + // Handle customer-specific fields + if ($auditableType === Customer::class) { + return [ + 'net_pay_days' => 'Net Pay Days', + 'billing_location_id' => 'Billing Location', + 'dba_name' => 'DBA Name', + 'invoice_number_schema' => 'Invoice Number Schema', + 'billing_contact_id' => 'Billing Contact', + 'organization_id' => 'Organization', + ]; } - return $changes; - } - - private function formatFieldName(string $field): string - { - return match ($field) { - 'net_pay_days' => 'Net Pay Days', - 'billing_location_id' => 'Billing Location', - 'dba_name' => 'DBA Name', - 'invoice_number_schema' => 'Invoice Number Schema', - 'billing_contact_id' => 'Billing Contact', - 'organization_id' => 'Organization', - default => ucwords(str_replace('_', ' ', $field)), - }; + return []; } } \ No newline at end of file diff --git a/app/Actions/Facilities/GetFacilityAuditHistory.php b/app/Actions/Facilities/GetFacilityAuditHistory.php new file mode 100644 index 00000000..f12e1717 --- /dev/null +++ b/app/Actions/Facilities/GetFacilityAuditHistory.php @@ -0,0 +1,52 @@ +getAuditHistory($facility); + return $this->formatAuditData($audits); + } + + public function asController(ActionRequest $request, Facility $facility) + { + $audits = $this->handle($facility); + return $this->jsonResponse($audits); + } + + public function jsonResponse($audits) + { + return response()->json([ + 'audits' => $audits, + ]); + } + + public function authorize(ActionRequest $request): bool + { + return $request->user()->can(\App\Enums\Permission::FACILITY_VIEW); + } + + protected function getModelSpecificFieldMappings(string $auditableType): array + { + // Handle facility-specific fields + if ($auditableType === Facility::class) { + return [ + 'location_id' => 'Location', + 'organization_id' => 'Organization', + ]; + } + + return []; + } +} \ No newline at end of file diff --git a/app/Models/Contact.php b/app/Models/Contact.php index bc68e776..665999ed 100644 --- a/app/Models/Contact.php +++ b/app/Models/Contact.php @@ -8,10 +8,12 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphTo; use Laravel\Scout\Searchable; +use OwenIt\Auditing\Contracts\Auditable; -class Contact extends Model +class Contact extends Model implements Auditable { use HasOrganization, Searchable, HasAliases; + use \OwenIt\Auditing\Auditable; protected $fillable = [ 'organization_id', diff --git a/app/Models/Documents/Document.php b/app/Models/Documents/Document.php index 3e329803..2f2522e9 100644 --- a/app/Models/Documents/Document.php +++ b/app/Models/Documents/Document.php @@ -10,10 +10,12 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; +use OwenIt\Auditing\Contracts\Auditable; -class Document extends Model +class Document extends Model implements Auditable { use HasOrganization, SoftDeletes; + use \OwenIt\Auditing\Auditable; protected $fillable = [ 'organization_id', diff --git a/app/Models/Facility.php b/app/Models/Facility.php index 47582ab6..7afcb297 100644 --- a/app/Models/Facility.php +++ b/app/Models/Facility.php @@ -12,10 +12,12 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Laravel\Scout\Searchable; +use OwenIt\Auditing\Contracts\Auditable; -class Facility extends Model +class Facility extends Model implements Auditable { use HasFactory, HasOrganization, Searchable, HasContacts, HasNotes, HasDocuments, HasAliases; + use \OwenIt\Auditing\Auditable; protected $fillable = [ 'organization_id', diff --git a/app/Traits/HandlesAuditHistory.php b/app/Traits/HandlesAuditHistory.php new file mode 100644 index 00000000..76fa59db --- /dev/null +++ b/app/Traits/HandlesAuditHistory.php @@ -0,0 +1,210 @@ +audits()->with('user')->get(); + + // Get document audits for documents belonging to this parent model + $documentAudits = $this->getRelatedModelAudits( + Document::class, + $parentClass, + $parentModel->id, + 'documentable_type', + 'documentable_id' + ); + + // Get contact audits for contacts belonging to this parent model + $contactAudits = $this->getRelatedModelAudits( + Contact::class, + $parentClass, + $parentModel->id, + 'contact_for_type', + 'contact_for_id' + ); + + // Merge all audits and sort by created_at desc + return $parentAudits->merge($documentAudits)->merge($contactAudits) + ->sortByDesc('created_at') + ->values(); + } + + private function getRelatedModelAudits( + string $auditableType, + string $parentClass, + int $parentId, + string $typeField, + string $idField + ): \Illuminate\Support\Collection { + return Audit::where('auditable_type', $auditableType) + ->where(function ($query) use ($parentClass, $parentId, $typeField, $idField) { + // Include audits where the model still exists + $query->whereHas('auditable', function ($subQuery) use ($parentClass, $parentId, $typeField, $idField) { + $subQuery->where($typeField, $parentClass) + ->where($idField, $parentId); + }) + // OR include audits where model was deleted but belonged to this parent + ->orWhere(function ($subQuery) use ($parentClass, $parentId, $typeField, $idField) { + $subQuery->whereDoesntHave('auditable') + ->where(function ($valueQuery) use ($parentClass, $parentId, $typeField, $idField) { + $valueQuery->whereJsonContains("old_values->{$typeField}", $parentClass) + ->whereJsonContains("old_values->{$idField}", $parentId) + ->orWhereJsonContains("new_values->{$typeField}", $parentClass) + ->whereJsonContains("new_values->{$idField}", $parentId); + }); + }); + }) + ->with('user', 'auditable') + ->get(); + } + + protected function formatAuditData(\Illuminate\Support\Collection $audits): \Illuminate\Support\Collection + { + return $audits->map(function (Audit $audit) { + return [ + 'id' => $audit->id, + 'event' => $audit->event, + 'auditable_type' => $audit->auditable_type, + 'auditable_id' => $audit->auditable_id, + 'entity_type' => $this->getEntityType($audit->auditable_type), + 'entity_name' => $this->getEntityName($audit), + 'user' => $audit->user ? [ + 'id' => $audit->user->id, + 'name' => $audit->user->name, + 'email' => $audit->user->email, + ] : null, + 'old_values' => $audit->old_values ?? [], + 'new_values' => $audit->new_values ?? [], + 'url' => $audit->url, + 'ip_address' => $audit->ip_address, + 'user_agent' => $audit->user_agent, + 'created_at' => $audit->created_at, + 'created_at_human' => $audit->created_at->diffForHumans(), + 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? [], $audit->auditable_type), + ]; + }); + } + + private function formatChanges(array $oldValues, array $newValues, string $auditableType): array + { + $changes = []; + $allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues))); + + // Filter out system fields we don't want to show in the UI + $systemFields = [ + 'id', + 'organization_id', + 'contact_for_id', + 'contact_for_type', + 'documentable_id', + 'documentable_type', + 'created_at', + 'updated_at' + ]; + + foreach ($allKeys as $key) { + // Skip system fields + if (in_array($key, $systemFields)) { + continue; + } + + $oldValue = $oldValues[$key] ?? null; + $newValue = $newValues[$key] ?? null; + + if ($oldValue !== $newValue) { + $changes[] = [ + 'field' => $this->formatFieldName($key, $auditableType), + 'field_name' => $key, + 'old_value' => $oldValue, + 'new_value' => $newValue, + ]; + } + } + + return $changes; + } + + private function formatFieldName(string $field, string $auditableType): string + { + // Get the specific field mappings for the parent model + $specificMappings = $this->getModelSpecificFieldMappings($auditableType); + + if (isset($specificMappings[$field])) { + return $specificMappings[$field]; + } + + // Handle document-specific fields + if ($auditableType === Document::class) { + return match ($field) { + 'uploaded_by' => 'Uploaded By', + 'folder_name' => 'Folder Name', + default => ucwords(str_replace('_', ' ', $field)), + }; + } + + // Handle contact-specific fields + if ($auditableType === Contact::class) { + return match ($field) { + 'contact_type' => 'Contact Type', + 'mobile_phone' => 'Mobile Phone', + 'office_phone' => 'Office Phone', + 'office_phone_extension' => 'Office Phone Extension', + default => ucwords(str_replace('_', ' ', $field)), + }; + } + + return ucwords(str_replace('_', ' ', $field)); + } + + private function getEntityType(string $auditableType): string + { + return match ($auditableType) { + \App\Models\Customers\Customer::class => 'Customer', + \App\Models\Facility::class => 'Facility', + \App\Models\Carriers\Carrier::class => 'Carrier', + Document::class => 'Document', + Contact::class => 'Contact', + default => class_basename($auditableType), + }; + } + + private function getEntityName(Audit $audit): string + { + if (!$audit->auditable) { + // For deleted entities, try to get name from old_values or new_values + $name = $audit->old_values['name'] ?? $audit->new_values['name'] ?? null; + + return match ($audit->auditable_type) { + \App\Models\Customers\Customer::class => $name ? $name . ' (deleted)' : 'Deleted Customer', + \App\Models\Facility::class => $name ? $name . ' (deleted)' : 'Deleted Facility', + \App\Models\Carriers\Carrier::class => $name ? $name . ' (deleted)' : 'Deleted Carrier', + Document::class => $name ? $name . ' (deleted)' : 'Deleted Document', + Contact::class => $name ? $name . ' (deleted)' : 'Deleted Contact', + default => 'Deleted Entity', + }; + } + + return match ($audit->auditable_type) { + \App\Models\Customers\Customer::class => $audit->auditable->name ?? 'Unknown Customer', + \App\Models\Facility::class => $audit->auditable->name ?? 'Unknown Facility', + \App\Models\Carriers\Carrier::class => $audit->auditable->name ?? 'Unknown Carrier', + Document::class => $audit->auditable->name ?? 'Unknown Document', + Contact::class => $audit->auditable->name ?? 'Unknown Contact', + default => 'Unknown Entity', + }; + } + + // Abstract method to be implemented by each audit action class + abstract protected function getModelSpecificFieldMappings(string $auditableType): array; +} \ No newline at end of file diff --git a/resources/js/Components/Audit/AuditFieldValue.tsx b/resources/js/Components/Audit/AuditFieldValue.tsx index 08054156..2d99641e 100644 --- a/resources/js/Components/Audit/AuditFieldValue.tsx +++ b/resources/js/Components/Audit/AuditFieldValue.tsx @@ -7,26 +7,32 @@ interface AuditFieldValueProps { fieldName: string; value: unknown; className?: string; + auditUser?: { + id: number; + name: string; + email: string; + } | null; } // Map of field names to their corresponding model types const FOREIGN_KEY_MAPPINGS: Record = { - 'billing_location_id': 'location', - 'physical_location_id': 'location', - 'location_id': 'location', - 'billing_contact_id': 'contact', - 'contact_id': 'contact', - 'user_id': 'user', - 'created_by': 'user', - 'updated_by': 'user', - 'carrier_id': 'carrier', - 'customer_id': 'customer', + billing_location_id: 'location', + physical_location_id: 'location', + location_id: 'location', + billing_contact_id: 'contact', + contact_id: 'contact', + user_id: 'user', + created_by: 'user', + updated_by: 'user', + carrier_id: 'carrier', + customer_id: 'customer', }; export default function AuditFieldValue({ fieldName, value, className = '', + auditUser, }: AuditFieldValueProps) { const [modalOpen, setModalOpen] = useState(false); @@ -40,7 +46,26 @@ export default function AuditFieldValue({ if (typeof value === 'object') { return JSON.stringify(value); } - return String(value); + + const stringValue = String(value); + + // Special handling for file paths + if (fieldName === 'path' && stringValue) { + // Extract just the filename from the path + const parts = stringValue.split('/'); + return parts[parts.length - 1] || stringValue; + } + + // Special handling for uploaded_by - show the user name if it matches the audit user + if ( + fieldName === 'uploaded_by' && + auditUser && + String(value) === String(auditUser.id) + ) { + return auditUser.name; + } + + return stringValue; }; // Check if this field is a foreign key @@ -74,4 +99,4 @@ export default function AuditFieldValue({ } return {formatValue(value)}; -} \ No newline at end of file +} diff --git a/resources/js/Components/Audit/AuditLinkedDataModal.tsx b/resources/js/Components/Audit/AuditLinkedDataModal.tsx index 64bc9356..74f36440 100644 --- a/resources/js/Components/Audit/AuditLinkedDataModal.tsx +++ b/resources/js/Components/Audit/AuditLinkedDataModal.tsx @@ -6,7 +6,7 @@ import { DialogTitle, } from '@/Components/ui/dialog'; import { Skeleton } from '@/Components/ui/skeleton'; -import { ExternalLink, X } from 'lucide-react'; +import { ExternalLink } from 'lucide-react'; import { useEffect, useState } from 'react'; interface LinkedData { @@ -44,7 +44,7 @@ export default function AuditLinkedDataModal({ try { setLoading(true); setError(null); - + const response = await fetch( route('audit.linked-data', { type: modelType, @@ -59,9 +59,7 @@ export default function AuditLinkedDataModal({ const data = await response.json(); setLinkedData(data); } catch (err) { - setError( - err instanceof Error ? err.message : 'An error occurred', - ); + setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setLoading(false); } @@ -70,7 +68,7 @@ export default function AuditLinkedDataModal({ const formatFieldName = (key: string): string => { return key .split('_') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); }; @@ -130,7 +128,9 @@ export default function AuditLinkedDataModal({ {error && (
-
Error loading data
+
+ Error loading data +
{error}
)} @@ -169,4 +169,4 @@ export default function AuditLinkedDataModal({ ); -} \ No newline at end of file +} diff --git a/resources/js/Components/Audit/AuditTable.tsx b/resources/js/Components/Audit/AuditTable.tsx index f2d5b575..29c68209 100644 --- a/resources/js/Components/Audit/AuditTable.tsx +++ b/resources/js/Components/Audit/AuditTable.tsx @@ -31,6 +31,10 @@ interface AuditChange { interface AuditEntry { id: number; event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; user: { id: number; name: string; @@ -176,11 +180,16 @@ export default function AuditTable({ audits, loading }: AuditTableProps) { }; const exportToCsv = () => { - const headers = ['Date', 'Event', 'User', 'Changes']; + const headers = ['Date', 'Event', 'User', 'Entity', 'Changes']; const csvData = filteredAndSortedAudits.map((audit) => [ new Date(audit.created_at).toLocaleString(), audit.event, audit.user?.name || 'System', + audit.entity_type && + (audit.entity_type === 'Document' || + audit.entity_type === 'Contact') + ? `${audit.entity_type}: ${audit.entity_name}` + : '-', audit.changes .map( (c) => @@ -350,6 +359,7 @@ export default function AuditTable({ audits, loading }: AuditTableProps) { )} + Entity Changes @@ -357,7 +367,7 @@ export default function AuditTable({ audits, loading }: AuditTableProps) { {filteredAndSortedAudits.length === 0 ? ( {audits.length === 0 @@ -407,6 +417,28 @@ export default function AuditTable({ audits, loading }: AuditTableProps) { )} + + {audit.entity_type && + (audit.entity_type === 'Document' || + audit.entity_type === + 'Contact') ? ( +
+ + {audit.entity_type} + +
+ {audit.entity_name} +
+
+ ) : ( + + - + + )} +
{audit.changes.length === 0 ? ( @@ -414,28 +446,56 @@ export default function AuditTable({ audits, loading }: AuditTableProps) { No changes ) : ( - audit.changes.map((change, changeIndex) => ( -
-
- {change.field} -
-
- - - - - - - + audit.changes.map( + ( + change, + changeIndex, + ) => ( +
+
+ { + change.field + } +
+
+ + + + + → + + + + +
-
- )) + ), + ) )}
diff --git a/resources/js/Components/Audit/AuditTimeline.tsx b/resources/js/Components/Audit/AuditTimeline.tsx index fc7bf1e1..b6303de8 100644 --- a/resources/js/Components/Audit/AuditTimeline.tsx +++ b/resources/js/Components/Audit/AuditTimeline.tsx @@ -15,6 +15,10 @@ interface AuditChange { interface AuditEntry { id: number; event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; user: { id: number; name: string; @@ -158,6 +162,18 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) { {getEventTitle(audit.event)} + {audit.entity_type && + (audit.entity_type === 'Document' || + audit.entity_type === + 'Contact') && ( + + {audit.entity_type}:{' '} + {audit.entity_name} + + )} {audit.user && (
@@ -185,8 +201,15 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) {
@@ -194,8 +217,15 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) {
@@ -234,8 +264,15 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) {
@@ -245,8 +282,15 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) {
diff --git a/resources/js/Components/Audit/CustomerAuditHistory.tsx b/resources/js/Components/Audit/CustomerAuditHistory.tsx index 7435d92a..f2cd0160 100644 --- a/resources/js/Components/Audit/CustomerAuditHistory.tsx +++ b/resources/js/Components/Audit/CustomerAuditHistory.tsx @@ -16,6 +16,10 @@ interface AuditChange { interface AuditEntry { id: number; event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; user: { id: number; name: string; @@ -119,4 +123,4 @@ export default function CustomerAuditHistory({ ); -} \ No newline at end of file +} diff --git a/resources/js/Components/Audit/FacilityAuditHistory.tsx b/resources/js/Components/Audit/FacilityAuditHistory.tsx new file mode 100644 index 00000000..f78fe484 --- /dev/null +++ b/resources/js/Components/Audit/FacilityAuditHistory.tsx @@ -0,0 +1,126 @@ +import { Card, CardContent } from '@/Components/ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; +import { Facility } from '@/types'; +import { Clock, Table } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import AuditTable from './AuditTable'; +import AuditTimeline from './AuditTimeline'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface FacilityAuditHistoryProps { + facility: Facility; +} + +export default function FacilityAuditHistory({ + facility, +}: FacilityAuditHistoryProps) { + const [audits, setAudits] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [activeTab, setActiveTab] = useState('timeline'); + + useEffect(() => { + const fetchAudits = async () => { + try { + setLoading(true); + const response = await fetch( + route('facilities.audit-history', facility.id), + ); + + if (!response.ok) { + throw new Error('Failed to fetch audit history'); + } + + const data = await response.json(); + setAudits(data.audits || []); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + if (facility.id) { + fetchAudits(); + } + }, [facility.id]); + + if (error) { + return ( + + +
+
+ Error loading audit history +
+
{error}
+
+
+
+ ); + } + + return ( +
+ + + + + Audit Timeline + + +
+ Audit Table + + + + + + + + + + + + + ); +} diff --git a/resources/js/Pages/Facilities/Partials/FacilityDetails.tsx b/resources/js/Pages/Facilities/Partials/FacilityDetails.tsx index c9b9c360..ae20cca6 100644 --- a/resources/js/Pages/Facilities/Partials/FacilityDetails.tsx +++ b/resources/js/Pages/Facilities/Partials/FacilityDetails.tsx @@ -1,3 +1,4 @@ +import FacilityAuditHistory from '@/Components/Audit/FacilityAuditHistory'; import ContactList from '@/Components/Contacts/ContactList/ContactList'; import LocationForm from '@/Components/CreateForms/LocationForm'; import DocumentsList from '@/Components/Documents/DocumentsList'; @@ -161,6 +162,7 @@ export default function FacilityDetails({ facility }: { facility: Facility }) { Shipment History + Audit History ) : ( @@ -189,6 +191,12 @@ export default function FacilityDetails({ facility }: { facility: Facility }) { > Shipment History + handleTabChange('audit')} + > + Audit History + )} @@ -375,6 +383,11 @@ export default function FacilityDetails({ facility }: { facility: Facility }) { + + {/* Audit History Tab */} + + + ); diff --git a/routes/web.php b/routes/web.php index 04e9118c..3bbdab0d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -30,6 +30,7 @@ use App\Actions\Documents\GetDocumentsWithFolders; use App\Actions\Documents\UpdateDocument; use App\Actions\Facilities\CreateFacility; +use App\Actions\Facilities\GetFacilityAuditHistory; use App\Actions\IntegrationSettings\DeleteIntegrationSetting; use App\Actions\IntegrationSettings\SetIntegrationSetting; use App\Actions\Locations\CreateLocation; @@ -179,6 +180,7 @@ ]); Route::post('facilities', CreateFacility::class)->name('facilities.store'); Route::put('facilities/{facility}', \App\Actions\Facilities\UpdateFacility::class)->name('facilities.update'); + Route::get('facilities/{facility}/audit-history', GetFacilityAuditHistory::class)->name('facilities.audit-history'); Route::get('carriers/search', [CarrierController::class, 'search'])->name('carriers.search'); Route::resource('carriers', CarrierController::class, [ From 680e2de6e0a340a8b00cdbbef9412f69384fc7c2 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Sat, 12 Jul 2025 16:25:53 -0400 Subject: [PATCH 3/7] Adding more details on audit views --- app/Actions/Audit/GetAuditLinkedData.php | 52 +- app/Traits/HandlesAuditHistory.php | 74 +- package-lock.json | 2543 +++++++---------- phpstan.neon | 8 +- .../Components/Audit/AuditLinkedDataModal.tsx | 18 +- .../js/Components/Audit/AuditTimeline.tsx | 13 - resources/js/Pages/Shipments/Create.tsx | 12 +- 7 files changed, 1174 insertions(+), 1546 deletions(-) diff --git a/app/Actions/Audit/GetAuditLinkedData.php b/app/Actions/Audit/GetAuditLinkedData.php index b5fa21b8..666bf0af 100644 --- a/app/Actions/Audit/GetAuditLinkedData.php +++ b/app/Actions/Audit/GetAuditLinkedData.php @@ -24,7 +24,7 @@ public function handle(string $type, int $id) } return [ - 'id' => $model->id, + 'id' => $model->getKey(), 'type' => $this->getDisplayType($type), 'title' => $this->getDisplayTitle($model, $type), 'data' => $this->getDisplayData($model, $type), @@ -77,16 +77,20 @@ private function getDisplayTitle(Model $model, string $type): string { return match ($type) { 'location' => $this->formatLocationTitle($model), - 'contact' => $model->name ?? 'Contact #' . $model->id, - 'carrier' => $model->name ?? 'Carrier #' . $model->id, - 'customer' => $model->name ?? 'Customer #' . $model->id, - 'user' => $model->name ?? 'User #' . $model->id, - default => ucfirst($type) . ' #' . $model->id, + 'contact' => ($model instanceof Contact ? $model->name : null) ?? 'Contact #' . $model->getKey(), + 'carrier' => ($model instanceof Carrier ? $model->name : null) ?? 'Carrier #' . $model->getKey(), + 'customer' => ($model instanceof Customer ? $model->name : null) ?? 'Customer #' . $model->getKey(), + 'user' => ($model instanceof User ? $model->name : null) ?? 'User #' . $model->getKey(), + default => ucfirst($type) . ' #' . $model->getKey(), }; } private function formatLocationTitle(Model $location): string { + if (!$location instanceof Location) { + return 'Location #' . $location->getKey(); + } + $parts = array_filter([ $location->name, $location->address_line_1, @@ -94,7 +98,7 @@ private function formatLocationTitle(Model $location): string $location->address_state, ]); - return implode(', ', $parts) ?: 'Location #' . $location->id; + return implode(', ', $parts) ?: 'Location #' . $location->getKey(); } private function getDisplayData(Model $model, string $type): array @@ -111,6 +115,10 @@ private function getDisplayData(Model $model, string $type): array private function getLocationData(Model $location): array { + if (!$location instanceof Location) { + return []; + } + return [ 'name' => $location->name, 'address_line_1' => $location->address_line_1, @@ -118,26 +126,36 @@ private function getLocationData(Model $location): array 'city' => $location->address_city, 'state' => $location->address_state, 'zipcode' => $location->address_zipcode, - 'country' => $location->address_country, - 'phone' => $location->phone, + 'latitude' => $location->latitude, + 'longitude' => $location->longitude, 'created_at' => $location->created_at?->format('M j, Y g:i A'), ]; } private function getContactData(Model $contact): array { + if (!$contact instanceof Contact) { + return []; + } + return [ 'name' => $contact->name, 'email' => $contact->email, - 'phone' => $contact->phone, + 'mobile_phone' => $contact->mobile_phone, + 'office_phone' => $contact->office_phone, + 'office_phone_extension' => $contact->office_phone_extension, 'title' => $contact->title, - 'notes' => $contact->notes, + 'contact_type' => $contact->contact_type, 'created_at' => $contact->created_at?->format('M j, Y g:i A'), ]; } private function getCarrierData(Model $carrier): array { + if (!$carrier instanceof Carrier) { + return []; + } + return [ 'name' => $carrier->name, 'mc_number' => $carrier->mc_number, @@ -152,6 +170,10 @@ private function getCarrierData(Model $carrier): array private function getCustomerData(Model $customer): array { + if (!$customer instanceof Customer) { + return []; + } + return [ 'name' => $customer->name, 'dba_name' => $customer->dba_name, @@ -163,6 +185,10 @@ private function getCustomerData(Model $customer): array private function getUserData(Model $user): array { + if (!$user instanceof User) { + return []; + } + return [ 'name' => $user->name, 'email' => $user->email, @@ -174,8 +200,8 @@ private function getViewUrl(Model $model, string $type): ?string { try { return match ($type) { - 'carrier' => route('carriers.show', $model->id), - 'customer' => route('customers.show', $model->id), + 'carrier' => route('carriers.show', $model->getKey()), + 'customer' => route('customers.show', $model->getKey()), 'location' => null, // Locations don't have individual view pages 'contact' => null, // Contacts don't have individual view pages 'user' => null, // Users don't have individual view pages typically diff --git a/app/Traits/HandlesAuditHistory.php b/app/Traits/HandlesAuditHistory.php index 76fa59db..30b9e5d3 100644 --- a/app/Traits/HandlesAuditHistory.php +++ b/app/Traits/HandlesAuditHistory.php @@ -5,11 +5,12 @@ use App\Models\Contact; use App\Models\Documents\Document; use Illuminate\Database\Eloquent\Model; +use OwenIt\Auditing\Contracts\Auditable; use OwenIt\Auditing\Models\Audit; trait HandlesAuditHistory { - protected function getAuditHistory(Model $parentModel): \Illuminate\Support\Collection + protected function getAuditHistory(Model & Auditable $parentModel): \Illuminate\Support\Collection { $parentClass = get_class($parentModel); @@ -20,7 +21,7 @@ protected function getAuditHistory(Model $parentModel): \Illuminate\Support\Coll $documentAudits = $this->getRelatedModelAudits( Document::class, $parentClass, - $parentModel->id, + $parentModel->getKey(), 'documentable_type', 'documentable_id' ); @@ -29,7 +30,7 @@ protected function getAuditHistory(Model $parentModel): \Illuminate\Support\Coll $contactAudits = $this->getRelatedModelAudits( Contact::class, $parentClass, - $parentModel->id, + $parentModel->getKey(), 'contact_for_type', 'contact_for_id' ); @@ -43,7 +44,7 @@ protected function getAuditHistory(Model $parentModel): \Illuminate\Support\Coll private function getRelatedModelAudits( string $auditableType, string $parentClass, - int $parentId, + mixed $parentId, string $typeField, string $idField ): \Illuminate\Support\Collection { @@ -72,26 +73,33 @@ private function getRelatedModelAudits( protected function formatAuditData(\Illuminate\Support\Collection $audits): \Illuminate\Support\Collection { return $audits->map(function (Audit $audit) { + /** @var mixed $auditableType */ + $auditableType = $audit->getAttributeValue('auditable_type'); + /** @var mixed $oldValues */ + $oldValues = $audit->getAttributeValue('old_values') ?? []; + /** @var mixed $newValues */ + $newValues = $audit->getAttributeValue('new_values') ?? []; + return [ - 'id' => $audit->id, - 'event' => $audit->event, - 'auditable_type' => $audit->auditable_type, - 'auditable_id' => $audit->auditable_id, - 'entity_type' => $this->getEntityType($audit->auditable_type), + 'id' => $audit->getKey(), + 'event' => $audit->getAttributeValue('event'), + 'auditable_type' => $auditableType, + 'auditable_id' => $audit->getAttributeValue('auditable_id'), + 'entity_type' => $this->getEntityType($auditableType), 'entity_name' => $this->getEntityName($audit), 'user' => $audit->user ? [ - 'id' => $audit->user->id, - 'name' => $audit->user->name, - 'email' => $audit->user->email, + 'id' => $audit->user->getKey(), + 'name' => $audit->user->getAttributeValue('name'), + 'email' => $audit->user->getAttributeValue('email'), ] : null, - 'old_values' => $audit->old_values ?? [], - 'new_values' => $audit->new_values ?? [], - 'url' => $audit->url, - 'ip_address' => $audit->ip_address, - 'user_agent' => $audit->user_agent, - 'created_at' => $audit->created_at, - 'created_at_human' => $audit->created_at->diffForHumans(), - 'changes' => $this->formatChanges($audit->old_values ?? [], $audit->new_values ?? [], $audit->auditable_type), + 'old_values' => $oldValues, + 'new_values' => $newValues, + 'url' => $audit->getAttributeValue('url'), + 'ip_address' => $audit->getAttributeValue('ip_address'), + 'user_agent' => $audit->getAttributeValue('user_agent'), + 'created_at' => $audit->getAttributeValue('created_at'), + 'created_at_human' => $audit->getAttributeValue('created_at')?->diffForHumans(), + 'changes' => $this->formatChanges($oldValues, $newValues, $auditableType), ]; }); } @@ -181,11 +189,19 @@ private function getEntityType(string $auditableType): string private function getEntityName(Audit $audit): string { - if (!$audit->auditable) { + $auditable = $audit->auditable; + /** @var mixed $auditableType */ + $auditableType = $audit->getAttributeValue('auditable_type'); + /** @var mixed $oldValues */ + $oldValues = $audit->getAttributeValue('old_values') ?? []; + /** @var mixed $newValues */ + $newValues = $audit->getAttributeValue('new_values') ?? []; + + if (!$auditable) { // For deleted entities, try to get name from old_values or new_values - $name = $audit->old_values['name'] ?? $audit->new_values['name'] ?? null; + $name = $oldValues['name'] ?? $newValues['name'] ?? null; - return match ($audit->auditable_type) { + return match ($auditableType) { \App\Models\Customers\Customer::class => $name ? $name . ' (deleted)' : 'Deleted Customer', \App\Models\Facility::class => $name ? $name . ' (deleted)' : 'Deleted Facility', \App\Models\Carriers\Carrier::class => $name ? $name . ' (deleted)' : 'Deleted Carrier', @@ -195,12 +211,12 @@ private function getEntityName(Audit $audit): string }; } - return match ($audit->auditable_type) { - \App\Models\Customers\Customer::class => $audit->auditable->name ?? 'Unknown Customer', - \App\Models\Facility::class => $audit->auditable->name ?? 'Unknown Facility', - \App\Models\Carriers\Carrier::class => $audit->auditable->name ?? 'Unknown Carrier', - Document::class => $audit->auditable->name ?? 'Unknown Document', - Contact::class => $audit->auditable->name ?? 'Unknown Contact', + return match ($auditableType) { + \App\Models\Customers\Customer::class => $auditable->getAttributeValue('name') ?? 'Unknown Customer', + \App\Models\Facility::class => $auditable->getAttributeValue('name') ?? 'Unknown Facility', + \App\Models\Carriers\Carrier::class => $auditable->getAttributeValue('name') ?? 'Unknown Carrier', + Document::class => $auditable->getAttributeValue('name') ?? 'Unknown Document', + Contact::class => $auditable->getAttributeValue('name') ?? 'Unknown Contact', default => 'Unknown Entity', }; } diff --git a/package-lock.json b/package-lock.json index 39bc30b3..d5e1c62a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,23 +101,23 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, "license": "MIT", "engines": { @@ -125,22 +125,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -166,15 +166,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -182,14 +182,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -208,29 +208,38 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -240,9 +249,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -250,27 +259,27 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -278,26 +287,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.28.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -307,13 +316,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -323,13 +332,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -339,57 +348,54 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -522,9 +528,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz", + "integrity": "sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==", "cpu": [ "ppc64" ], @@ -539,9 +545,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.6.tgz", + "integrity": "sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==", "cpu": [ "arm" ], @@ -556,9 +562,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz", + "integrity": "sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==", "cpu": [ "arm64" ], @@ -573,9 +579,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.6.tgz", + "integrity": "sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==", "cpu": [ "x64" ], @@ -590,9 +596,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz", + "integrity": "sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==", "cpu": [ "arm64" ], @@ -607,9 +613,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz", + "integrity": "sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==", "cpu": [ "x64" ], @@ -624,9 +630,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz", + "integrity": "sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==", "cpu": [ "arm64" ], @@ -641,9 +647,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz", + "integrity": "sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==", "cpu": [ "x64" ], @@ -658,9 +664,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz", + "integrity": "sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==", "cpu": [ "arm" ], @@ -675,9 +681,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz", + "integrity": "sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==", "cpu": [ "arm64" ], @@ -692,9 +698,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz", + "integrity": "sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==", "cpu": [ "ia32" ], @@ -709,9 +715,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz", + "integrity": "sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==", "cpu": [ "loong64" ], @@ -726,9 +732,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz", + "integrity": "sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==", "cpu": [ "mips64el" ], @@ -743,9 +749,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz", + "integrity": "sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==", "cpu": [ "ppc64" ], @@ -760,9 +766,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz", + "integrity": "sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==", "cpu": [ "riscv64" ], @@ -777,9 +783,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz", + "integrity": "sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==", "cpu": [ "s390x" ], @@ -794,9 +800,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz", + "integrity": "sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==", "cpu": [ "x64" ], @@ -811,9 +817,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz", + "integrity": "sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==", "cpu": [ "arm64" ], @@ -828,9 +834,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz", + "integrity": "sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==", "cpu": [ "x64" ], @@ -845,9 +851,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz", + "integrity": "sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==", "cpu": [ "arm64" ], @@ -862,9 +868,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz", + "integrity": "sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==", "cpu": [ "x64" ], @@ -878,10 +884,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz", + "integrity": "sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz", + "integrity": "sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==", "cpu": [ "x64" ], @@ -896,9 +919,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz", + "integrity": "sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==", "cpu": [ "arm64" ], @@ -913,9 +936,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz", + "integrity": "sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==", "cpu": [ "ia32" ], @@ -930,9 +953,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz", + "integrity": "sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==", "cpu": [ "x64" ], @@ -947,9 +970,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1000,9 +1023,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1010,22 +1033,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1050,22 +1057,22 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", - "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", + "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", + "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.7.2", + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react": { @@ -1085,12 +1092,12 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz", + "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@floating-ui/dom": "^1.7.2" }, "peerDependencies": { "react": ">=16.8.0", @@ -1098,9 +1105,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, "node_modules/@googlemaps/js-api-loader": { @@ -1120,16 +1127,17 @@ } }, "node_modules/@headlessui/react": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.1.tgz", - "integrity": "sha512-daiUqVLae8CKVjEVT19P/izW0aGK0GNhMSAeMlrDebKmoVZHcRRwbxzgtnEadUVDXyBsWo9/UH4KHeniO+0tMg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz", + "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==", "dev": true, "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.16", - "@react-aria/focus": "^3.17.1", - "@react-aria/interactions": "^3.21.3", - "@tanstack/react-virtual": "^3.11.1" + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" }, "engines": { "node": ">=10" @@ -1165,9 +1173,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1211,27 +1219,26 @@ "license": "BSD-3-Clause" }, "node_modules/@inertiajs/core": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.0.6.tgz", - "integrity": "sha512-Jv3NQdN0rX2lS+SXpMQfBWfD0dRp9F1eKrZvpX6pOO4DInSMD7gjCVnYs+zbYFa6Fbgms0mQnnQHvwlT6W+TSA==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.0.14.tgz", + "integrity": "sha512-6LLr+8PFqjwRh9JZMuM+L3TksHagS34bg2e3/j9LBHGFv3DGw3JxZaHm+PWqqgKAfOrgs4HFtiU1bEo/anzzAA==", "dev": true, "license": "MIT", "dependencies": { "axios": "^1.8.2", - "deepmerge": "^4.0.0", + "es-toolkit": "^1.34.1", "qs": "^6.9.0" } }, "node_modules/@inertiajs/react": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-2.0.6.tgz", - "integrity": "sha512-FyF4W92LXrHGEC2WAjaVe3t+E58zfIvz0OnGCvWiti4nzVRidqYo8TMaokPuoH2B6uTwhoJvys6l50zRxgbzuA==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-2.0.14.tgz", + "integrity": "sha512-GAjb+jkJKEbuY5qMxC3RIu8/+/eaBszo20zHWd4ZdJ+bX09Pd+GUzRAPf0bSLO86ilccT/GsACX8eE9CccZboQ==", "dev": true, "license": "MIT", "dependencies": { - "@inertiajs/core": "2.0.6", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" + "@inertiajs/core": "2.0.14", + "es-toolkit": "^1.33.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -1334,17 +1341,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -1356,25 +1359,16 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1427,45 +1421,45 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", - "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@radix-ui/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", "license": "MIT" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", "license": "MIT" }, "node_modules/@radix-ui/react-accordion": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.3.tgz", - "integrity": "sha512-RIQ15mrcvqIkDARJeERSuXSry2N8uYnxkdDetpfmalT/+0ntOXLkFOsh9iwlAsCv+qcmhZjbdJogIm6WBa6c4A==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.11.tgz", + "integrity": "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collapsible": "1.1.3", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collapsible": "1.1.11", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -1483,17 +1477,17 @@ } }, "node_modules/@radix-ui/react-alert-dialog": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.6.tgz", - "integrity": "sha512-p4XnPqgej8sZAAReCAKgz1REYZEBLR8hU9Pg27wFnCWIMc8g1ccCs0FjBcy05V15VTu8pAePw/VDYeOm/uZ6yQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.14.tgz", + "integrity": "sha512-IOZfZ3nPvN6lXpJTBCunFQPRSvK8MDgSc1FB85xnIpUKOw9en0dJj8JmCAxV7BiZdtYlUpmrQjoTFkVYtdoWzQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dialog": "1.1.6", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -1510,31 +1504,13 @@ } } }, - "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz", - "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -1552,15 +1528,16 @@ } }, "node_modules/@radix-ui/react-avatar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.3.tgz", - "integrity": "sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", "license": "MIT", "dependencies": { - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1578,19 +1555,19 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz", - "integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1608,19 +1585,19 @@ } }, "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz", - "integrity": "sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", + "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1638,15 +1615,15 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", - "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -1663,28 +1640,10 @@ } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1697,9 +1656,9 @@ } }, "node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1712,23 +1671,23 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz", - "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -1747,28 +1706,10 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1781,16 +1722,16 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", - "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1808,18 +1749,18 @@ } }, "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz", - "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==", + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz", + "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.6", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -1837,9 +1778,9 @@ } }, "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1852,14 +1793,14 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", - "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1877,12 +1818,12 @@ } }, "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -1895,12 +1836,12 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.2.tgz", - "integrity": "sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -1918,27 +1859,27 @@ } }, "node_modules/@radix-ui/react-menu": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.6.tgz", - "integrity": "sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-roving-focus": "1.1.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-callback-ref": "1.1.0", + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz", + "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -1957,43 +1898,25 @@ } } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "node_modules/@radix-ui/react-popover": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popover": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.6.tgz", - "integrity": "sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -2012,40 +1935,22 @@ } } }, - "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-popper": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz", - "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2063,13 +1968,13 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", - "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2087,13 +1992,13 @@ } }, "node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", + "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2111,12 +2016,12 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.1.2" + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -2133,123 +2038,34 @@ } } }, - "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.4.tgz", - "integrity": "sha512-8rl9w7lJdcVPor47Dhws9mUHRHLE+8JEgyJRdNWCpGPa6HIlr3eh+Yn9gyx1CnCLbw5naHsI2gaO9dBWO50vzw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.0.tgz", - "integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-slot": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz", - "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, "node_modules/@radix-ui/react-radio-group": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.6.tgz", - "integrity": "sha512-1tfTAqnYZNVwSpFhCT273nzK8qGBReeYnNTPspCggqk1fvIrfVxJekIuBFidNivzpdiMqDwVGnQvHqXrRPM4Og==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz", + "integrity": "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", @@ -2257,8 +2073,8 @@ "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.2", - "@radix-ui/react-roving-focus": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" @@ -2278,22 +2094,21 @@ } } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", - "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.6.tgz", - "integrity": "sha512-PbhRFK4lIEw9ADonj48tiYWzkllz81TM7KVYyyMMw2cwHO7D5h4XKEblL8NlaRisTK3QTe6tBEhDccFUryxHBQ==", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", "license": "MIT", "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.2", - "@radix-ui/react-slot": "1.2.2" + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -2310,76 +2125,20 @@ } } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", - "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz", + "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", "license": "MIT", "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { @@ -2397,247 +2156,31 @@ } } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.2.tgz", - "integrity": "sha512-uHa+l/lKfxuDD2zjN/0peM/RhhSmRjr5YWdk/37EnSv1nJ88uvG85DPexSm8HdFQROd2VdERJ6ynXbkCFi+APw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.9.tgz", - "integrity": "sha512-ZzrIFnMYHHCNqSNCsuN6l7wlewBEq0O0BCSBkabJMFXVO51LRUTq71gLP1UxFvmrXElqmPjA5VX7IqC9VpazAQ==", + "node_modules/@radix-ui/react-select": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", "license": "MIT", "dependencies": { + "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-collection": "1.1.6", + "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.2", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.2.tgz", - "integrity": "sha512-y7TBO4xN4Y94FvcWIOIh18fM4R1A8S4q1jhoz4PNzOoHsFcN8pogcFmZrTYAm4F9VRUrWP/Mw7xSKybIeRI+CQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-previous": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", - "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.3.tgz", - "integrity": "sha512-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz", - "integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -2656,31 +2199,13 @@ } } }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-separator": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.2.tgz", - "integrity": "sha512-oZfHcaAp2Y6KFBX6I5P1u7CQoy4lheCGiYj+pGFrHy8E/VNRb5E39TkTr3JrV520csPBTZjkuKFdEsjS5EUNKQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -2699,27 +2224,12 @@ }, "node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2731,18 +2241,18 @@ } }, "node_modules/@radix-ui/react-switch": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.3.tgz", - "integrity": "sha512-1nc+vjEOQkJVsJtWPSiISGT6OKm4SiOdjMo+/icLxo2G4vxz1GntC5MzfL4v8ey9OEfw787QCD1y3mUv0NiFEQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.5.tgz", + "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2760,19 +2270,19 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz", - "integrity": "sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz", + "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-roving-focus": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -2790,23 +2300,23 @@ } }, "node_modules/@radix-ui/react-toast": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.6.tgz", - "integrity": "sha512-gN4dpuIVKEgpLn1z5FhzT9mYRUitbfZq9XqN/7kkBMUgFTzTG8x/KszWJugJXHcwxckY8xcKDZPz7kG3o6DsUA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2" + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.14.tgz", + "integrity": "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -2824,23 +2334,23 @@ } }, "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.8.tgz", - "integrity": "sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", + "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -2857,28 +2367,10 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2891,12 +2383,13 @@ } }, "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2926,11 +2419,14 @@ } } }, - "node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/react-use-escape-keydown": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2941,13 +2437,13 @@ } } }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", @@ -2960,9 +2456,9 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2975,9 +2471,9 @@ } }, "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2990,12 +2486,12 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.0" + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3008,12 +2504,12 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3026,12 +2522,12 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", - "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -3049,21 +2545,21 @@ } }, "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, "node_modules/@react-aria/focus": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.1.tgz", - "integrity": "sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw==", + "version": "3.20.5", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.5.tgz", + "integrity": "sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.24.1", - "@react-aria/utils": "^3.28.1", - "@react-types/shared": "^3.28.0", + "@react-aria/interactions": "^3.25.3", + "@react-aria/utils": "^3.29.1", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3073,16 +2569,16 @@ } }, "node_modules/@react-aria/interactions": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz", - "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.3.tgz", + "integrity": "sha512-J1bhlrNtjPS/fe5uJQ+0c7/jiXniwa4RQlP+Emjfc/iuqpW2RhbF9ou5vROcLzWIyaW8tVMZ468J68rAs/aZ5A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.28.1", - "@react-stately/flags": "^3.1.0", - "@react-types/shared": "^3.28.0", + "@react-aria/ssr": "^3.9.9", + "@react-aria/utils": "^3.29.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3091,9 +2587,9 @@ } }, "node_modules/@react-aria/ssr": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz", - "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==", + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.9.tgz", + "integrity": "sha512-2P5thfjfPy/np18e5wD4WPt8ydNXhij1jwA8oehxZTFqlgVMGXzcWKxTb4RtJrLFsqPO7RUQTiY8QJk0M4Vy2g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3107,16 +2603,16 @@ } }, "node_modules/@react-aria/utils": { - "version": "3.28.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz", - "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.1.tgz", + "integrity": "sha512-yXMFVJ73rbQ/yYE/49n5Uidjw7kh192WNN9PNQGV0Xoc7EJUlSOxqhnpHmYTyO0EotJ8fdM1fMH8durHjUSI8g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.7", - "@react-stately/flags": "^3.1.0", - "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.28.0", + "@react-aria/ssr": "^3.9.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.7", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3126,9 +2622,9 @@ } }, "node_modules/@react-google-maps/api": { - "version": "2.20.6", - "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.20.6.tgz", - "integrity": "sha512-frxkSHWbd36ayyxrEVopSCDSgJUT1tVKXvQld2IyzU3UnDuqqNA3AZE4/fCdqQb2/zBQx3nrWnZB1wBXDcrjcw==", + "version": "2.20.7", + "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.20.7.tgz", + "integrity": "sha512-ys7uri3V6gjhYZUI43srHzSKDC6/jiKTwHNlwXFTvjeaJE3M3OaYBt9FZKvJs8qnOhL6i6nD1BKJoi1KrnkCkg==", "license": "MIT", "dependencies": { "@googlemaps/js-api-loader": "1.16.8", @@ -3156,9 +2652,9 @@ "license": "MIT" }, "node_modules/@react-stately/flags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.0.tgz", - "integrity": "sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3166,9 +2662,9 @@ } }, "node_modules/@react-stately/utils": { - "version": "3.10.5", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz", - "integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==", + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.7.tgz", + "integrity": "sha512-cWvjGAocvy4abO9zbr6PW6taHgF24Mwy/LbQ4TC4Aq3tKdKDntxyD+sh7AkSRfJRT2ccMVaHVv2+FfHThd3PKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3179,19 +2675,26 @@ } }, "node_modules/@react-types/shared": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", - "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.30.0.tgz", + "integrity": "sha512-COIazDAx1ncDg046cTJ8SFYsX8aS3lB/08LDnbkH/SkdYrFPWDlXMrO/sUam8j1WWM+PJ+4d1mj7tODIKNiFog==", "dev": true, "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", + "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", - "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", + "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", "cpu": [ "arm" ], @@ -3203,9 +2706,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", - "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", + "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", "cpu": [ "arm64" ], @@ -3217,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", - "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", + "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", "cpu": [ "arm64" ], @@ -3231,9 +2734,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", - "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", + "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", "cpu": [ "x64" ], @@ -3245,9 +2748,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", - "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", + "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", "cpu": [ "arm64" ], @@ -3259,9 +2762,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", - "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", + "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", "cpu": [ "x64" ], @@ -3273,9 +2776,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", - "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", + "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", "cpu": [ "arm" ], @@ -3287,9 +2790,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", - "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", + "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", "cpu": [ "arm" ], @@ -3301,9 +2804,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", - "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", + "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", "cpu": [ "arm64" ], @@ -3315,9 +2818,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", - "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", + "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", "cpu": [ "arm64" ], @@ -3329,9 +2832,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", - "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", + "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", "cpu": [ "loong64" ], @@ -3343,9 +2846,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", - "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", + "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", "cpu": [ "ppc64" ], @@ -3357,9 +2860,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", - "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", + "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", "cpu": [ "riscv64" ], @@ -3371,9 +2874,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", - "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", + "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", "cpu": [ "riscv64" ], @@ -3385,9 +2888,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", - "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", + "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", "cpu": [ "s390x" ], @@ -3399,9 +2902,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", - "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", + "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", "cpu": [ "x64" ], @@ -3413,9 +2916,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", - "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", + "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", "cpu": [ "x64" ], @@ -3427,9 +2930,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", - "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", + "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", "cpu": [ "arm64" ], @@ -3441,9 +2944,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", - "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", + "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", "cpu": [ "ia32" ], @@ -3455,9 +2958,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", - "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", + "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", "cpu": [ "x64" ], @@ -3469,9 +2972,9 @@ ] }, "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3492,12 +2995,12 @@ } }, "node_modules/@tanstack/react-table": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz", - "integrity": "sha512-11tNlEDTdIhMJba2RBH+ecJ9l1zgS2kjmexDPAraulc8jeNA4xocSNeyzextT0XJyASil4XsCYlJmf5jEWAtYg==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", "license": "MIT", "dependencies": { - "@tanstack/table-core": "8.21.2" + "@tanstack/table-core": "8.21.3" }, "engines": { "node": ">=12" @@ -3512,13 +3015,13 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.13.6", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.6.tgz", - "integrity": "sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", + "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", "dev": true, "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.13.6" + "@tanstack/virtual-core": "3.13.12" }, "funding": { "type": "github", @@ -3530,9 +3033,9 @@ } }, "node_modules/@tanstack/table-core": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.2.tgz", - "integrity": "sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", "license": "MIT", "engines": { "node": ">=12" @@ -3543,9 +3046,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.13.6", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz", - "integrity": "sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", + "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", "dev": true, "license": "MIT", "funding": { @@ -3605,9 +3108,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -3627,9 +3130,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.86", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.86.tgz", - "integrity": "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ==", + "version": "18.19.118", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.118.tgz", + "integrity": "sha512-hIPK0hSrrcaoAu/gJMzN3QClXE4QdCdFvaenJ0JsjIbExP1JFFVH+RHcBt25c9n8bx5dkIfqKE+uw6BmBns7ug==", "dev": true, "license": "MIT", "dependencies": { @@ -3643,15 +3146,15 @@ "license": "MIT" }, "node_modules/@types/prop-types": { - "version": "15.7.14", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", - "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -3659,9 +3162,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.3.6", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz", - "integrity": "sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==", + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", "peerDependencies": { @@ -3878,29 +3381,30 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", - "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz", + "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@babel/core": "^7.27.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.19", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" + "react-refresh": "^0.17.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3994,9 +3498,9 @@ "license": "Python-2.0" }, "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -4023,18 +3527,20 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4232,9 +3738,9 @@ } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "dev": true, "license": "MIT", "dependencies": { @@ -4297,9 +3803,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -4318,9 +3824,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -4338,10 +3844,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -4419,9 +3925,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001710", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001710.tgz", - "integrity": "sha512-B5C0I0UmaGqHgo5FuqJ7hBd4L57A4dDD+Xi+XX1nXOoxGeDdY4Ko38qJYOyqznBVJEqON5p8P1x5zRR3+rsnxA==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "dev": true, "funding": [ { @@ -4615,9 +4121,9 @@ "license": "MIT" }, "node_modules/concurrently": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", - "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.0.tgz", + "integrity": "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4775,9 +4281,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4798,16 +4304,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -4930,9 +4426,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.132", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.132.tgz", - "integrity": "sha512-QgX9EBvWGmvSRa74zqfnG7+Eno0Ak0vftBll0Pt2/z5b3bEGYL6OUXLgKPtvx73dn3dvwrlyVkjPKRRlhLYTEg==", + "version": "1.5.182", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz", + "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==", "dev": true, "license": "ISC" }, @@ -4952,9 +4448,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, "license": "MIT", "dependencies": { @@ -4962,18 +4458,18 @@ "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -4985,21 +4481,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -5008,7 +4507,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -5125,10 +4624,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.39.7", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.7.tgz", + "integrity": "sha512-ek/wWryKouBrZIjkwW2BFf91CWOIMvoy2AE5YYgUrfWsJQM2Su1LoLtrw8uusEpN9RfqLlV/0FVNjT0WMv8Bxw==", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz", + "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5139,31 +4649,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@esbuild/aix-ppc64": "0.25.6", + "@esbuild/android-arm": "0.25.6", + "@esbuild/android-arm64": "0.25.6", + "@esbuild/android-x64": "0.25.6", + "@esbuild/darwin-arm64": "0.25.6", + "@esbuild/darwin-x64": "0.25.6", + "@esbuild/freebsd-arm64": "0.25.6", + "@esbuild/freebsd-x64": "0.25.6", + "@esbuild/linux-arm": "0.25.6", + "@esbuild/linux-arm64": "0.25.6", + "@esbuild/linux-ia32": "0.25.6", + "@esbuild/linux-loong64": "0.25.6", + "@esbuild/linux-mips64el": "0.25.6", + "@esbuild/linux-ppc64": "0.25.6", + "@esbuild/linux-riscv64": "0.25.6", + "@esbuild/linux-s390x": "0.25.6", + "@esbuild/linux-x64": "0.25.6", + "@esbuild/netbsd-arm64": "0.25.6", + "@esbuild/netbsd-x64": "0.25.6", + "@esbuild/openbsd-arm64": "0.25.6", + "@esbuild/openbsd-x64": "0.25.6", + "@esbuild/openharmony-arm64": "0.25.6", + "@esbuild/sunos-x64": "0.25.6", + "@esbuild/win32-arm64": "0.25.6", + "@esbuild/win32-ia32": "0.25.6", + "@esbuild/win32-x64": "0.25.6" } }, "node_modules/escalade": { @@ -5259,14 +4770,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz", - "integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", + "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.0" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -5336,9 +4847,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -5413,9 +4924,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -5423,22 +4934,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5722,15 +5217,16 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -5933,9 +5429,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -5957,12 +5453,19 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -6434,6 +5937,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -6774,9 +6290,9 @@ } }, "node_modules/laravel-vite-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", - "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.3.0.tgz", + "integrity": "sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==", "dev": true, "license": "MIT", "dependencies": { @@ -6848,21 +6364,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7407,9 +6908,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -7426,7 +6927,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7580,9 +7081,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -7626,9 +7127,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", - "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz", + "integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==", "dev": true, "license": "MIT", "engines": { @@ -7636,6 +7137,8 @@ }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", @@ -7657,6 +7160,12 @@ "@ianvs/prettier-plugin-sort-imports": { "optional": true }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, "@prettier/plugin-pug": { "optional": true }, @@ -7781,14 +7290,14 @@ } }, "node_modules/react-day-picker": { - "version": "9.6.4", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.6.4.tgz", - "integrity": "sha512-OekyAWfaypSFN5zms4CD6Bcas5R0KbWdARkWTyQ2phJHQOolDfpLwrN6Q+U3ifPGNmKLf9ngXuSz25NKHMkR6w==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.8.0.tgz", + "integrity": "sha512-E0yhhg7R+pdgbl/2toTb0xBhsEAtmAx1l7qjIWYfcxOy8w4rTSVfbtBoSzVVhPwKP/5E9iL38LivzoE3AQDhCQ==", "license": "MIT", "dependencies": { - "@date-fns/tz": "^1.2.0", - "date-fns": "^4.1.0", - "date-fns-jalali": "^4.1.0-0" + "@date-fns/tz": "1.2.0", + "date-fns": "4.1.0", + "date-fns-jalali": "4.1.0-0" }, "engines": { "node": ">=18" @@ -7858,9 +7367,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.55.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.55.0.tgz", - "integrity": "sha512-XRnjsH3GVMQz1moZTW53MxfoWN7aDpUg/GpVNc4A3eXRVNdGXfbzJ4vM4aLQ8g6XCUh1nIbx70aaNCl7kxnjog==", + "version": "7.60.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", + "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -7880,9 +7389,9 @@ "license": "MIT" }, "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -7890,9 +7399,9 @@ } }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", @@ -7937,9 +7446,9 @@ } }, "node_modules/react-select": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.1.tgz", - "integrity": "sha512-roPEZUL4aRZDx6DcsD+ZNreVl+fM8VsKn0Wtex1v4IazH60ILp5xhdlp464IsEAlJdXeD+BhDAFsBVMfvLQueA==", + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", + "integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.0", @@ -8039,12 +7548,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -8131,13 +7634,13 @@ } }, "node_modules/rollup": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", - "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.2.tgz", + "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -8147,26 +7650,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.39.0", - "@rollup/rollup-android-arm64": "4.39.0", - "@rollup/rollup-darwin-arm64": "4.39.0", - "@rollup/rollup-darwin-x64": "4.39.0", - "@rollup/rollup-freebsd-arm64": "4.39.0", - "@rollup/rollup-freebsd-x64": "4.39.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", - "@rollup/rollup-linux-arm-musleabihf": "4.39.0", - "@rollup/rollup-linux-arm64-gnu": "4.39.0", - "@rollup/rollup-linux-arm64-musl": "4.39.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-musl": "4.39.0", - "@rollup/rollup-linux-s390x-gnu": "4.39.0", - "@rollup/rollup-linux-x64-gnu": "4.39.0", - "@rollup/rollup-linux-x64-musl": "4.39.0", - "@rollup/rollup-win32-arm64-msvc": "4.39.0", - "@rollup/rollup-win32-ia32-msvc": "4.39.0", - "@rollup/rollup-win32-x64-msvc": "4.39.0", + "@rollup/rollup-android-arm-eabi": "4.44.2", + "@rollup/rollup-android-arm64": "4.44.2", + "@rollup/rollup-darwin-arm64": "4.44.2", + "@rollup/rollup-darwin-x64": "4.44.2", + "@rollup/rollup-freebsd-arm64": "4.44.2", + "@rollup/rollup-freebsd-x64": "4.44.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", + "@rollup/rollup-linux-arm-musleabihf": "4.44.2", + "@rollup/rollup-linux-arm64-gnu": "4.44.2", + "@rollup/rollup-linux-arm64-musl": "4.44.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-musl": "4.44.2", + "@rollup/rollup-linux-s390x-gnu": "4.44.2", + "@rollup/rollup-linux-x64-gnu": "4.44.2", + "@rollup/rollup-linux-x64-musl": "4.44.2", + "@rollup/rollup-win32-arm64-msvc": "4.44.2", + "@rollup/rollup-win32-ia32-msvc": "4.44.2", + "@rollup/rollup-win32-x64-msvc": "4.44.2", "fsevents": "~2.3.2" } }, @@ -8268,9 +7771,9 @@ } }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -8351,9 +7854,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { @@ -8479,6 +7982,20 @@ "node": ">=0.10.0" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -8730,14 +8247,13 @@ } }, "node_modules/synckit": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.2.tgz", - "integrity": "sha512-1IUffI8zZ8qUMB3NUJIjk0RpLroG/8NkQDAWH1NbB2iJ0/5pn3M8rxfNzMz4GH9OnYaGYn31LEDSXJp/qIlxgA==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.0", - "tslib": "^2.8.1" + "@pkgr/core": "^0.2.4" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -8857,6 +8373,51 @@ "node": ">=0.8" } }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9009,9 +8570,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9120,9 +8681,9 @@ } }, "node_modules/use-isomorphic-layout-effect": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", - "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -9155,6 +8716,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9162,15 +8732,18 @@ "license": "MIT" }, "node_modules/vite": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", - "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -9244,6 +8817,34 @@ "picomatch": "^2.3.1" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -9419,15 +9020,15 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yargs": { @@ -9473,9 +9074,9 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/phpstan.neon b/phpstan.neon index ce93b6dd..671a39cf 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,8 +10,10 @@ parameters: # Level 10 is the highest level level: 5 -# ignoreErrors: -# - '#PHPDoc tag @var#' -# + ignoreErrors: + # Laravel Auditing package stubs are missing these relationships + - '#Relation ''user'' is not found in OwenIt\\Auditing\\Models\\Audit model#' + - '#Relation ''auditable'' is not found in OwenIt\\Auditing\\Models\\Audit model#' + # excludePaths: # - ./*/*/FileToBeExcluded.php \ No newline at end of file diff --git a/resources/js/Components/Audit/AuditLinkedDataModal.tsx b/resources/js/Components/Audit/AuditLinkedDataModal.tsx index 74f36440..b9f25b23 100644 --- a/resources/js/Components/Audit/AuditLinkedDataModal.tsx +++ b/resources/js/Components/Audit/AuditLinkedDataModal.tsx @@ -7,7 +7,7 @@ import { } from '@/Components/ui/dialog'; import { Skeleton } from '@/Components/ui/skeleton'; import { ExternalLink } from 'lucide-react'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; interface LinkedData { id: number; @@ -34,13 +34,7 @@ export default function AuditLinkedDataModal({ const [loading, setLoading] = useState(false); const [error, setError] = useState(null); - useEffect(() => { - if (open && modelId && modelType) { - fetchLinkedData(); - } - }, [open, modelId, modelType]); - - const fetchLinkedData = async () => { + const fetchLinkedData = useCallback(async () => { try { setLoading(true); setError(null); @@ -63,7 +57,13 @@ export default function AuditLinkedDataModal({ } finally { setLoading(false); } - }; + }, [modelType, modelId]); + + useEffect(() => { + if (open && modelId && modelType) { + fetchLinkedData(); + } + }, [open, modelId, modelType, fetchLinkedData]); const formatFieldName = (key: string): string => { return key diff --git a/resources/js/Components/Audit/AuditTimeline.tsx b/resources/js/Components/Audit/AuditTimeline.tsx index b6303de8..e7a1f06b 100644 --- a/resources/js/Components/Audit/AuditTimeline.tsx +++ b/resources/js/Components/Audit/AuditTimeline.tsx @@ -92,19 +92,6 @@ export default function AuditTimeline({ audits, loading }: AuditTimelineProps) { } }; - const formatValue = (value: unknown): string => { - if (value === null || value === undefined) { - return 'No value'; - } - if (typeof value === 'boolean') { - return value ? 'Yes' : 'No'; - } - if (typeof value === 'object') { - return JSON.stringify(value); - } - return String(value); - }; - if (loading) { return (
diff --git a/resources/js/Pages/Shipments/Create.tsx b/resources/js/Pages/Shipments/Create.tsx index 115d817a..9a2c060d 100644 --- a/resources/js/Pages/Shipments/Create.tsx +++ b/resources/js/Pages/Shipments/Create.tsx @@ -658,10 +658,8 @@ export default function Create({ 'stops', stops, { - shouldValidate: - false, - shouldTouch: - false, + shouldValidate: false, + shouldTouch: false, }, ); }} @@ -699,10 +697,8 @@ export default function Create({ 'stops', stops, { - shouldValidate: - false, - shouldTouch: - false, + shouldValidate: false, + shouldTouch: false, }, ); }} From 19f15c07601b7a07dccf3406fe44716a51933933 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Sat, 12 Jul 2025 16:29:31 -0400 Subject: [PATCH 4/7] Fix TypeScript build errors in IntegrationSettingsTable Remove conflicting index signature from IntegrationSettingForm that was causing TypeScript compilation failures after dependency updates. Changed from interface with index signature to type alias to resolve form errors type inference issues with useForm from Inertia.js. --- .../Pages/Organizations/Partials/IntegrationSettingsTable.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx b/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx index 20620b4b..cde4fd35 100644 --- a/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx +++ b/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx @@ -34,12 +34,11 @@ interface Props { globalIntegrationSettings: GlobalIntegrationSetting[]; } -interface IntegrationSettingForm { +type IntegrationSettingForm = { key: string; value: string; provider?: string; expose_to_frontend: boolean; - [key: string]: string | boolean | undefined; } interface ProviderGroup { From 102ab0916b6b340fefb205d1182d9fc428921c68 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Sat, 12 Jul 2025 16:41:14 -0400 Subject: [PATCH 5/7] Fixing build errors --- app/Console/Commands/PreCommitChecks.php | 2 +- package-lock.json | 174 +++++++++--------- .../Partials/IntegrationSettingsTable.tsx | 2 +- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/app/Console/Commands/PreCommitChecks.php b/app/Console/Commands/PreCommitChecks.php index 3963a0d6..af79757b 100644 --- a/app/Console/Commands/PreCommitChecks.php +++ b/app/Console/Commands/PreCommitChecks.php @@ -31,7 +31,7 @@ class PreCommitChecks extends Command ]; protected $commands = [ - 'phpstan' => 'php ./vendor/bin/phpstan analyse', + 'phpstan' => 'php ./vendor/bin/phpstan analyse --memory-limit=1024M', 'npm-lint' => 'npm run lint', 'typescript' => 'npm exec tsc', 'npm-build' => 'npm run build', diff --git a/package-lock.json b/package-lock.json index d5e1c62a..46c8aa70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "html", + "name": "tms", "lockfileVersion": 3, "requires": true, "packages": { @@ -389,9 +389,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -2692,9 +2692,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", - "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.0.tgz", + "integrity": "sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg==", "cpu": [ "arm" ], @@ -2706,9 +2706,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", - "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.0.tgz", + "integrity": "sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ==", "cpu": [ "arm64" ], @@ -2720,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", - "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.0.tgz", + "integrity": "sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg==", "cpu": [ "arm64" ], @@ -2734,9 +2734,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", - "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.0.tgz", + "integrity": "sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA==", "cpu": [ "x64" ], @@ -2748,9 +2748,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", - "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.0.tgz", + "integrity": "sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA==", "cpu": [ "arm64" ], @@ -2762,9 +2762,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", - "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.0.tgz", + "integrity": "sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw==", "cpu": [ "x64" ], @@ -2776,9 +2776,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", - "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.0.tgz", + "integrity": "sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA==", "cpu": [ "arm" ], @@ -2790,9 +2790,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", - "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.0.tgz", + "integrity": "sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw==", "cpu": [ "arm" ], @@ -2804,9 +2804,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", - "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.0.tgz", + "integrity": "sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g==", "cpu": [ "arm64" ], @@ -2818,9 +2818,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", - "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.0.tgz", + "integrity": "sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg==", "cpu": [ "arm64" ], @@ -2832,9 +2832,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", - "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.0.tgz", + "integrity": "sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA==", "cpu": [ "loong64" ], @@ -2846,9 +2846,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", - "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.0.tgz", + "integrity": "sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw==", "cpu": [ "ppc64" ], @@ -2860,9 +2860,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", - "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.0.tgz", + "integrity": "sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w==", "cpu": [ "riscv64" ], @@ -2874,9 +2874,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", - "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.0.tgz", + "integrity": "sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA==", "cpu": [ "riscv64" ], @@ -2888,9 +2888,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", - "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.0.tgz", + "integrity": "sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g==", "cpu": [ "s390x" ], @@ -2902,9 +2902,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", - "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.0.tgz", + "integrity": "sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw==", "cpu": [ "x64" ], @@ -2916,9 +2916,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", - "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.0.tgz", + "integrity": "sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ==", "cpu": [ "x64" ], @@ -2930,9 +2930,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", - "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.0.tgz", + "integrity": "sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ==", "cpu": [ "arm64" ], @@ -2944,9 +2944,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", - "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.0.tgz", + "integrity": "sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug==", "cpu": [ "ia32" ], @@ -2958,9 +2958,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", - "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.0.tgz", + "integrity": "sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA==", "cpu": [ "x64" ], @@ -7634,9 +7634,9 @@ } }, "node_modules/rollup": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.2.tgz", - "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.0.tgz", + "integrity": "sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A==", "dev": true, "license": "MIT", "dependencies": { @@ -7650,26 +7650,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.2", - "@rollup/rollup-android-arm64": "4.44.2", - "@rollup/rollup-darwin-arm64": "4.44.2", - "@rollup/rollup-darwin-x64": "4.44.2", - "@rollup/rollup-freebsd-arm64": "4.44.2", - "@rollup/rollup-freebsd-x64": "4.44.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", - "@rollup/rollup-linux-arm-musleabihf": "4.44.2", - "@rollup/rollup-linux-arm64-gnu": "4.44.2", - "@rollup/rollup-linux-arm64-musl": "4.44.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-musl": "4.44.2", - "@rollup/rollup-linux-s390x-gnu": "4.44.2", - "@rollup/rollup-linux-x64-gnu": "4.44.2", - "@rollup/rollup-linux-x64-musl": "4.44.2", - "@rollup/rollup-win32-arm64-msvc": "4.44.2", - "@rollup/rollup-win32-ia32-msvc": "4.44.2", - "@rollup/rollup-win32-x64-msvc": "4.44.2", + "@rollup/rollup-android-arm-eabi": "4.45.0", + "@rollup/rollup-android-arm64": "4.45.0", + "@rollup/rollup-darwin-arm64": "4.45.0", + "@rollup/rollup-darwin-x64": "4.45.0", + "@rollup/rollup-freebsd-arm64": "4.45.0", + "@rollup/rollup-freebsd-x64": "4.45.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.45.0", + "@rollup/rollup-linux-arm-musleabihf": "4.45.0", + "@rollup/rollup-linux-arm64-gnu": "4.45.0", + "@rollup/rollup-linux-arm64-musl": "4.45.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.45.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.45.0", + "@rollup/rollup-linux-riscv64-gnu": "4.45.0", + "@rollup/rollup-linux-riscv64-musl": "4.45.0", + "@rollup/rollup-linux-s390x-gnu": "4.45.0", + "@rollup/rollup-linux-x64-gnu": "4.45.0", + "@rollup/rollup-linux-x64-musl": "4.45.0", + "@rollup/rollup-win32-arm64-msvc": "4.45.0", + "@rollup/rollup-win32-ia32-msvc": "4.45.0", + "@rollup/rollup-win32-x64-msvc": "4.45.0", "fsevents": "~2.3.2" } }, diff --git a/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx b/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx index cde4fd35..1bedc9ee 100644 --- a/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx +++ b/resources/js/Pages/Organizations/Partials/IntegrationSettingsTable.tsx @@ -39,7 +39,7 @@ type IntegrationSettingForm = { value: string; provider?: string; expose_to_frontend: boolean; -} +}; interface ProviderGroup { name: string; From 45dbe162c2d103f46bcec36d13ffacad781124db Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Sat, 12 Jul 2025 20:49:46 -0400 Subject: [PATCH 6/7] Adding shipment audits --- _ide_helper_actions.php | 14 +++ .../Shipments/GetShipmentAuditHistory.php | 60 +++++++++++++ app/Models/Shipments/Shipment.php | 6 +- app/Traits/HandlesAuditHistory.php | 52 +++++++---- .../Components/Audit/ShipmentAuditHistory.tsx | 89 +++++++++++++++++++ resources/js/Pages/Shipments/Show.tsx | 7 +- routes/web.php | 2 + 7 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 app/Actions/Shipments/GetShipmentAuditHistory.php create mode 100644 resources/js/Components/Audit/ShipmentAuditHistory.tsx diff --git a/_ide_helper_actions.php b/_ide_helper_actions.php index d004569f..416f705d 100644 --- a/_ide_helper_actions.php +++ b/_ide_helper_actions.php @@ -860,6 +860,20 @@ class DispatchShipment class GetShipmentAccounting { } +/** + * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Shipments\Shipment $shipment) + * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Shipments\Shipment $shipment) + * @method static \Illuminate\Foundation\Bus\PendingDispatch dispatch(\App\Models\Shipments\Shipment $shipment) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchIf(bool $boolean, \App\Models\Shipments\Shipment $shipment) + * @method static \Illuminate\Foundation\Bus\PendingDispatch|\Illuminate\Support\Fluent dispatchUnless(bool $boolean, \App\Models\Shipments\Shipment $shipment) + * @method static dispatchSync(\App\Models\Shipments\Shipment $shipment) + * @method static dispatchNow(\App\Models\Shipments\Shipment $shipment) + * @method static dispatchAfterResponse(\App\Models\Shipments\Shipment $shipment) + * @method static mixed run(\App\Models\Shipments\Shipment $shipment) + */ +class GetShipmentAuditHistory +{ +} /** * @method static \Lorisleiva\Actions\Decorators\JobDecorator|\Lorisleiva\Actions\Decorators\UniqueJobDecorator makeJob(\App\Models\Shipments\Shipment $shipment, ?\App\Services\Shipments\ShipmentStateService $stateService = null) * @method static \Lorisleiva\Actions\Decorators\UniqueJobDecorator makeUniqueJob(\App\Models\Shipments\Shipment $shipment, ?\App\Services\Shipments\ShipmentStateService $stateService = null) diff --git a/app/Actions/Shipments/GetShipmentAuditHistory.php b/app/Actions/Shipments/GetShipmentAuditHistory.php new file mode 100644 index 00000000..b3d2b8cb --- /dev/null +++ b/app/Actions/Shipments/GetShipmentAuditHistory.php @@ -0,0 +1,60 @@ +getAuditHistory($shipment); + return $this->formatAuditData($audits); + } + + public function asController(ActionRequest $request, Shipment $shipment) + { + $audits = $this->handle($shipment); + return $this->jsonResponse($audits); + } + + public function jsonResponse($audits) + { + return response()->json([ + 'audits' => $audits, + ]); + } + + public function authorize(ActionRequest $request, Shipment $shipment): bool + { + return $request->user()->can('view', $shipment); + } + + protected function getModelSpecificFieldMappings(string $auditableType): array + { + if ($auditableType === Shipment::class) { + return [ + 'organization_id' => 'Organization', + 'carrier_id' => 'Carrier', + 'driver_id' => 'Driver', + 'weight' => 'Weight', + 'trip_distance' => 'Trip Distance', + 'trailer_type_id' => 'Trailer Type', + 'trailer_size_id' => 'Trailer Size', + 'trailer_temperature_range' => 'Temperature Controlled', + 'trailer_temperature' => 'Temperature', + 'trailer_temperature_maximum' => 'Maximum Temperature', + 'shipment_number' => 'Shipment Number', + 'state' => 'Status', + ]; + } + + return []; + } +} \ No newline at end of file diff --git a/app/Models/Shipments/Shipment.php b/app/Models/Shipments/Shipment.php index 578237eb..e0312e61 100644 --- a/app/Models/Shipments/Shipment.php +++ b/app/Models/Shipments/Shipment.php @@ -23,12 +23,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Laravel\Scout\Searchable; +use OwenIt\Auditing\Contracts\Auditable; +use OwenIt\Auditing\Auditable as AuditableTrait; use Spatie\ModelStates\HasStates; use Spatie\ModelStates\HasStatesContract; -class Shipment extends Model implements HasStatesContract +class Shipment extends Model implements HasStatesContract, Auditable { - use HasOrganization, Searchable, HasFactory, HasNotes, HasStates, HasDocuments, HasAliases; + use HasOrganization, Searchable, HasFactory, HasNotes, HasStates, HasDocuments, HasAliases, AuditableTrait; protected $fillable = [ 'organization_id', diff --git a/app/Traits/HandlesAuditHistory.php b/app/Traits/HandlesAuditHistory.php index 30b9e5d3..9ee8e8b0 100644 --- a/app/Traits/HandlesAuditHistory.php +++ b/app/Traits/HandlesAuditHistory.php @@ -48,26 +48,40 @@ private function getRelatedModelAudits( string $typeField, string $idField ): \Illuminate\Support\Collection { - return Audit::where('auditable_type', $auditableType) - ->where(function ($query) use ($parentClass, $parentId, $typeField, $idField) { - // Include audits where the model still exists - $query->whereHas('auditable', function ($subQuery) use ($parentClass, $parentId, $typeField, $idField) { - $subQuery->where($typeField, $parentClass) - ->where($idField, $parentId); - }) - // OR include audits where model was deleted but belonged to this parent - ->orWhere(function ($subQuery) use ($parentClass, $parentId, $typeField, $idField) { - $subQuery->whereDoesntHave('auditable') - ->where(function ($valueQuery) use ($parentClass, $parentId, $typeField, $idField) { - $valueQuery->whereJsonContains("old_values->{$typeField}", $parentClass) - ->whereJsonContains("old_values->{$idField}", $parentId) - ->orWhereJsonContains("new_values->{$typeField}", $parentClass) - ->whereJsonContains("new_values->{$idField}", $parentId); - }); - }); + $audits = collect(); + + // Get audits for models that currently exist and belong to this parent + $existingModelAudits = Audit::where('auditable_type', $auditableType) + ->whereHas('auditable', function ($subQuery) use ($parentClass, $parentId, $typeField, $idField) { + $subQuery->where($typeField, $parentClass) + ->where($idField, $parentId); }) ->with('user', 'auditable') ->get(); + + $audits = $audits->merge($existingModelAudits); + + // Get audits for deleted models - but be very precise to avoid cross-contamination + $deletedModelAudits = Audit::where('auditable_type', $auditableType) + ->whereDoesntHave('auditable') + ->get() + ->filter(function (Audit $audit) use ($parentClass, $parentId, $typeField, $idField) { + $oldValues = $audit->getAttributeValue('old_values') ?? []; + $newValues = $audit->getAttributeValue('new_values') ?? []; + + // Check if this audit belongs to our specific parent + $matchesInOld = isset($oldValues[$typeField]) && isset($oldValues[$idField]) && + $oldValues[$typeField] === $parentClass && + (int)$oldValues[$idField] === (int)$parentId; + + $matchesInNew = isset($newValues[$typeField]) && isset($newValues[$idField]) && + $newValues[$typeField] === $parentClass && + (int)$newValues[$idField] === (int)$parentId; + + return $matchesInOld || $matchesInNew; + }); + + return $audits->merge($deletedModelAudits); } protected function formatAuditData(\Illuminate\Support\Collection $audits): \Illuminate\Support\Collection @@ -181,6 +195,7 @@ private function getEntityType(string $auditableType): string \App\Models\Customers\Customer::class => 'Customer', \App\Models\Facility::class => 'Facility', \App\Models\Carriers\Carrier::class => 'Carrier', + \App\Models\Shipments\Shipment::class => 'Shipment', Document::class => 'Document', Contact::class => 'Contact', default => class_basename($auditableType), @@ -200,11 +215,13 @@ private function getEntityName(Audit $audit): string if (!$auditable) { // For deleted entities, try to get name from old_values or new_values $name = $oldValues['name'] ?? $newValues['name'] ?? null; + $shipmentNumber = $oldValues['shipment_number'] ?? $newValues['shipment_number'] ?? null; return match ($auditableType) { \App\Models\Customers\Customer::class => $name ? $name . ' (deleted)' : 'Deleted Customer', \App\Models\Facility::class => $name ? $name . ' (deleted)' : 'Deleted Facility', \App\Models\Carriers\Carrier::class => $name ? $name . ' (deleted)' : 'Deleted Carrier', + \App\Models\Shipments\Shipment::class => $shipmentNumber ? 'Shipment ' . $shipmentNumber . ' (deleted)' : 'Deleted Shipment', Document::class => $name ? $name . ' (deleted)' : 'Deleted Document', Contact::class => $name ? $name . ' (deleted)' : 'Deleted Contact', default => 'Deleted Entity', @@ -215,6 +232,7 @@ private function getEntityName(Audit $audit): string \App\Models\Customers\Customer::class => $auditable->getAttributeValue('name') ?? 'Unknown Customer', \App\Models\Facility::class => $auditable->getAttributeValue('name') ?? 'Unknown Facility', \App\Models\Carriers\Carrier::class => $auditable->getAttributeValue('name') ?? 'Unknown Carrier', + \App\Models\Shipments\Shipment::class => $auditable->getAttributeValue('shipment_number') ? 'Shipment ' . $auditable->getAttributeValue('shipment_number') : 'Shipment #' . $auditable->getKey(), Document::class => $auditable->getAttributeValue('name') ?? 'Unknown Document', Contact::class => $auditable->getAttributeValue('name') ?? 'Unknown Contact', default => 'Unknown Entity', diff --git a/resources/js/Components/Audit/ShipmentAuditHistory.tsx b/resources/js/Components/Audit/ShipmentAuditHistory.tsx new file mode 100644 index 00000000..7aa3d22b --- /dev/null +++ b/resources/js/Components/Audit/ShipmentAuditHistory.tsx @@ -0,0 +1,89 @@ +import { Card, CardContent } from '@/Components/ui/card'; +import { Shipment } from '@/types'; +import { useEffect, useState } from 'react'; +import AuditTimeline from './AuditTimeline'; + +interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +interface AuditEntry { + id: number; + event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +} + +interface ShipmentAuditHistoryProps { + shipment: Shipment; +} + +export default function ShipmentAuditHistory({ + shipment, +}: ShipmentAuditHistoryProps) { + const [audits, setAudits] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchAudits = async () => { + try { + setLoading(true); + const response = await fetch( + route('shipments.audit-history', shipment.id), + ); + + if (!response.ok) { + throw new Error('Failed to fetch audit history'); + } + + const data = await response.json(); + setAudits(data.audits || []); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + if (shipment.id) { + fetchAudits(); + } + }, [shipment.id]); + + if (error) { + return ( + + +
+
+ Error loading audit history +
+
{error}
+
+
+
+ ); + } + + return ; +} diff --git a/resources/js/Pages/Shipments/Show.tsx b/resources/js/Pages/Shipments/Show.tsx index 826b7e29..ab076bae 100644 --- a/resources/js/Pages/Shipments/Show.tsx +++ b/resources/js/Pages/Shipments/Show.tsx @@ -1,7 +1,7 @@ +import ShipmentAuditHistory from '@/Components/Audit/ShipmentAuditHistory'; import DocumentsList from '@/Components/Documents/DocumentsList'; import LocationMap from '@/Components/Shipments/LocationMap'; import { Card, CardContent, CardHeader, CardTitle } from '@/Components/ui/card'; -import { ComingSoon } from '@/Components/ui/coming-soon'; import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; import { Shipment, ShipmentStop, TrailerSize, TrailerType } from '@/types'; import { Documentable } from '@/types/enums'; @@ -102,10 +102,7 @@ export default function Show({ Recent Activity - + diff --git a/routes/web.php b/routes/web.php index 3bbdab0d..71f175bc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -42,6 +42,7 @@ use App\Actions\Shipments\CreateShipment; use App\Actions\Shipments\DispatchShipment; use App\Actions\Shipments\GetShipmentAccounting; +use App\Actions\Shipments\GetShipmentAuditHistory; use App\Actions\Shipments\UncancelShipment; use App\Actions\Shipments\UpdateShipmentCarrierDetails; use App\Actions\Shipments\UpdateShipmentGeneral; @@ -248,6 +249,7 @@ Route::get('shipments/{shipment}/accounting', GetShipmentAccounting::class)->name('shipments.accounting'); Route::post('shipments/{shipment}/accounting/payables', SavePayables::class)->name('shipments.accounting.payables'); Route::post('shipments/{shipment}/accounting/receivables', SaveReceivables::class)->name('shipments.accounting.receivables'); + Route::get('shipments/{shipment}/audit-history', GetShipmentAuditHistory::class)->name('shipments.audit-history'); Route::post('shipments/{shipment}/documents/generate-rate-con', GenerateRateConfirmation::class)->name('shipments.documents.generate-rate-confirmation'); Route::post('shipments/{shipment}/documents/generate-customer-invoice/{customer}', GenerateCustomerInvoice::class)->name('shipments.documents.generate-customer-invoice'); From f60b95fb12dc9001ee9fab58250dc1d8e8a2dad8 Mon Sep 17 00:00:00 2001 From: Nick Sorrell Date: Mon, 14 Jul 2025 10:34:13 -0400 Subject: [PATCH 7/7] DRY up audit components, fix path on Docs, fix database for testing/pipeline --- app/Console/Commands/PreCommitChecks.php | 6 +- config/database.php | 5 + .../js/Components/Audit/AuditFieldValue.tsx | 19 +++ .../js/Components/Audit/AuditHistory.tsx | 104 +++++++++++++++ .../Components/Audit/CarrierAuditHistory.tsx | 116 +---------------- .../Components/Audit/CustomerAuditHistory.tsx | 120 +----------------- .../Components/Audit/FacilityAuditHistory.tsx | 120 +----------------- .../Components/Audit/ShipmentAuditHistory.tsx | 87 ++----------- resources/js/Components/Audit/types.ts | 27 ++++ 9 files changed, 184 insertions(+), 420 deletions(-) create mode 100644 resources/js/Components/Audit/AuditHistory.tsx create mode 100644 resources/js/Components/Audit/types.ts diff --git a/app/Console/Commands/PreCommitChecks.php b/app/Console/Commands/PreCommitChecks.php index af79757b..41007a3c 100644 --- a/app/Console/Commands/PreCommitChecks.php +++ b/app/Console/Commands/PreCommitChecks.php @@ -53,12 +53,12 @@ public function handle() // Refresh testing database before running tests if ($check === 'tests:php') { - $this->refreshTestingDatabase(); $env = [ 'APP_ENV' => 'testing', 'DB_CONNECTION' => 'sqlite', 'DB_DATABASE' => ':memory:', ]; + $this->refreshTestingDatabase(); } $this->info("========== Running $check =========="); @@ -156,13 +156,13 @@ protected function refreshTestingDatabase(): void // Override the database configuration for testing config([ 'database.connections.sqlite.database' => ':memory:', - 'database.default' => 'sqlite', + 'database.default' => 'sqlite_testing', ]); $this->call('migrate:fresh', [ '--env' => 'testing', '--seed' => true, - '--database' => 'sqlite', + '--database' => 'sqlite_testing', ]); $this->info("Testing database refreshed successfully"); } catch (\Exception $e) { diff --git a/config/database.php b/config/database.php index 19b685bb..7b213fc6 100644 --- a/config/database.php +++ b/config/database.php @@ -42,6 +42,11 @@ 'synchronous' => null, ], + 'sqlite_testing' => [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ], + // connector for doing zip 3 to timezone lookups 'zip3_to_timezone' => [ 'driver' => 'sqlite', diff --git a/resources/js/Components/Audit/AuditFieldValue.tsx b/resources/js/Components/Audit/AuditFieldValue.tsx index 2d99641e..c9fad42b 100644 --- a/resources/js/Components/Audit/AuditFieldValue.tsx +++ b/resources/js/Components/Audit/AuditFieldValue.tsx @@ -37,10 +37,24 @@ export default function AuditFieldValue({ const [modalOpen, setModalOpen] = useState(false); const formatValue = (value: unknown): string => { + // Check for folder-related fields (both raw and formatted names) + const isFolderField = fieldName === 'folder_name' || fieldName === 'Folder Name'; + const isPathField = fieldName === 'path' || fieldName === 'Path'; + if (value === null || value === undefined) { + // For path fields, only show '/' if the value was explicitly set to null/undefined + // but not when there was no previous value (which should show 'No value') return 'No value'; } if (typeof value === 'boolean') { + // Special handling for folder fields - don't convert to Yes/No + if (isFolderField) { + return value ? 'true' : '/'; + } + // Special handling for path fields - show root folder when false + if (isPathField) { + return value ? 'true' : '/'; + } return value ? 'Yes' : 'No'; } if (typeof value === 'object') { @@ -49,6 +63,11 @@ export default function AuditFieldValue({ const stringValue = String(value); + // Special handling for folder fields - show root folder when empty + if (isFolderField && stringValue.trim() === '') { + return '/'; + } + // Special handling for file paths if (fieldName === 'path' && stringValue) { // Extract just the filename from the path diff --git a/resources/js/Components/Audit/AuditHistory.tsx b/resources/js/Components/Audit/AuditHistory.tsx new file mode 100644 index 00000000..ea5d7335 --- /dev/null +++ b/resources/js/Components/Audit/AuditHistory.tsx @@ -0,0 +1,104 @@ +import { Card, CardContent } from '@/Components/ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; +import { Clock, Table } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import AuditTable from './AuditTable'; +import AuditTimeline from './AuditTimeline'; +import { AuditEntry } from './types'; + +interface AuditHistoryProps { + entityId: number; + routeName: string; + showTabs?: boolean; +} + +export default function AuditHistory({ + entityId, + routeName, + showTabs = true, +}: AuditHistoryProps) { + const [audits, setAudits] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [activeTab, setActiveTab] = useState('timeline'); + + useEffect(() => { + const fetchAudits = async () => { + try { + setLoading(true); + const response = await fetch(route(routeName, entityId)); + + if (!response.ok) { + throw new Error('Failed to fetch audit history'); + } + + const data = await response.json(); + setAudits(data.audits || []); + } catch (err) { + setError( + err instanceof Error ? err.message : 'An error occurred', + ); + } finally { + setLoading(false); + } + }; + + if (entityId) { + fetchAudits(); + } + }, [entityId, routeName]); + + if (error) { + return ( + + +
+
+ Error loading audit history +
+
{error}
+
+
+
+ ); + } + + if (!showTabs) { + return ; + } + + return ( +
+ + + + + Audit Timeline + + +
+ Audit Table + + + + + + + + + + + + + ); +} diff --git a/resources/js/Components/Audit/CarrierAuditHistory.tsx b/resources/js/Components/Audit/CarrierAuditHistory.tsx index 5edd7f92..06536847 100644 --- a/resources/js/Components/Audit/CarrierAuditHistory.tsx +++ b/resources/js/Components/Audit/CarrierAuditHistory.tsx @@ -1,34 +1,5 @@ -import { Card, CardContent } from '@/Components/ui/card'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; import { Carrier } from '@/types'; -import { Clock, Table } from 'lucide-react'; -import { useEffect, useState } from 'react'; -import AuditTable from './AuditTable'; -import AuditTimeline from './AuditTimeline'; - -interface AuditChange { - field: string; - field_name: string; - old_value: unknown; - new_value: unknown; -} - -interface AuditEntry { - id: number; - event: string; - user: { - id: number; - name: string; - email: string; - } | null; - old_values: Record; - new_values: Record; - changes: AuditChange[]; - created_at: string; - created_at_human: string; - ip_address?: string; - user_agent?: string; -} +import AuditHistory from './AuditHistory'; interface CarrierAuditHistoryProps { carrier: Carrier; @@ -37,86 +8,11 @@ interface CarrierAuditHistoryProps { export default function CarrierAuditHistory({ carrier, }: CarrierAuditHistoryProps) { - const [audits, setAudits] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState('timeline'); - - useEffect(() => { - const fetchAudits = async () => { - try { - setLoading(true); - const response = await fetch( - route('carriers.audit-history', carrier.id), - ); - - if (!response.ok) { - throw new Error('Failed to fetch audit history'); - } - - const data = await response.json(); - setAudits(data.audits || []); - } catch (err) { - setError( - err instanceof Error ? err.message : 'An error occurred', - ); - } finally { - setLoading(false); - } - }; - - if (carrier.id) { - fetchAudits(); - } - }, [carrier.id]); - - if (error) { - return ( - - -
-
- Error loading audit history -
-
{error}
-
-
-
- ); - } - return ( -
- - - - - Audit Timeline - - -
- Audit Table - - - - - - - - - - - - + ); } diff --git a/resources/js/Components/Audit/CustomerAuditHistory.tsx b/resources/js/Components/Audit/CustomerAuditHistory.tsx index f2cd0160..70eb7940 100644 --- a/resources/js/Components/Audit/CustomerAuditHistory.tsx +++ b/resources/js/Components/Audit/CustomerAuditHistory.tsx @@ -1,38 +1,5 @@ -import { Card, CardContent } from '@/Components/ui/card'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; import { Customer } from '@/types'; -import { Clock, Table } from 'lucide-react'; -import { useEffect, useState } from 'react'; -import AuditTable from './AuditTable'; -import AuditTimeline from './AuditTimeline'; - -interface AuditChange { - field: string; - field_name: string; - old_value: unknown; - new_value: unknown; -} - -interface AuditEntry { - id: number; - event: string; - auditable_type?: string; - auditable_id?: number; - entity_type?: string; - entity_name?: string; - user: { - id: number; - name: string; - email: string; - } | null; - old_values: Record; - new_values: Record; - changes: AuditChange[]; - created_at: string; - created_at_human: string; - ip_address?: string; - user_agent?: string; -} +import AuditHistory from './AuditHistory'; interface CustomerAuditHistoryProps { customer: Customer; @@ -41,86 +8,11 @@ interface CustomerAuditHistoryProps { export default function CustomerAuditHistory({ customer, }: CustomerAuditHistoryProps) { - const [audits, setAudits] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState('timeline'); - - useEffect(() => { - const fetchAudits = async () => { - try { - setLoading(true); - const response = await fetch( - route('customers.audit-history', customer.id), - ); - - if (!response.ok) { - throw new Error('Failed to fetch audit history'); - } - - const data = await response.json(); - setAudits(data.audits || []); - } catch (err) { - setError( - err instanceof Error ? err.message : 'An error occurred', - ); - } finally { - setLoading(false); - } - }; - - if (customer.id) { - fetchAudits(); - } - }, [customer.id]); - - if (error) { - return ( - - -
-
- Error loading audit history -
-
{error}
-
-
-
- ); - } - return ( -
- - - - - Audit Timeline - - -
- Audit Table - - - - - - - - - - - - + ); } diff --git a/resources/js/Components/Audit/FacilityAuditHistory.tsx b/resources/js/Components/Audit/FacilityAuditHistory.tsx index f78fe484..3509ecaa 100644 --- a/resources/js/Components/Audit/FacilityAuditHistory.tsx +++ b/resources/js/Components/Audit/FacilityAuditHistory.tsx @@ -1,38 +1,5 @@ -import { Card, CardContent } from '@/Components/ui/card'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; import { Facility } from '@/types'; -import { Clock, Table } from 'lucide-react'; -import { useEffect, useState } from 'react'; -import AuditTable from './AuditTable'; -import AuditTimeline from './AuditTimeline'; - -interface AuditChange { - field: string; - field_name: string; - old_value: unknown; - new_value: unknown; -} - -interface AuditEntry { - id: number; - event: string; - auditable_type?: string; - auditable_id?: number; - entity_type?: string; - entity_name?: string; - user: { - id: number; - name: string; - email: string; - } | null; - old_values: Record; - new_values: Record; - changes: AuditChange[]; - created_at: string; - created_at_human: string; - ip_address?: string; - user_agent?: string; -} +import AuditHistory from './AuditHistory'; interface FacilityAuditHistoryProps { facility: Facility; @@ -41,86 +8,11 @@ interface FacilityAuditHistoryProps { export default function FacilityAuditHistory({ facility, }: FacilityAuditHistoryProps) { - const [audits, setAudits] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [activeTab, setActiveTab] = useState('timeline'); - - useEffect(() => { - const fetchAudits = async () => { - try { - setLoading(true); - const response = await fetch( - route('facilities.audit-history', facility.id), - ); - - if (!response.ok) { - throw new Error('Failed to fetch audit history'); - } - - const data = await response.json(); - setAudits(data.audits || []); - } catch (err) { - setError( - err instanceof Error ? err.message : 'An error occurred', - ); - } finally { - setLoading(false); - } - }; - - if (facility.id) { - fetchAudits(); - } - }, [facility.id]); - - if (error) { - return ( - - -
-
- Error loading audit history -
-
{error}
-
-
-
- ); - } - return ( -
- - - - - Audit Timeline - - -
- Audit Table - - - - - - - - - - - - + ); } diff --git a/resources/js/Components/Audit/ShipmentAuditHistory.tsx b/resources/js/Components/Audit/ShipmentAuditHistory.tsx index 7aa3d22b..79588dd7 100644 --- a/resources/js/Components/Audit/ShipmentAuditHistory.tsx +++ b/resources/js/Components/Audit/ShipmentAuditHistory.tsx @@ -1,35 +1,5 @@ -import { Card, CardContent } from '@/Components/ui/card'; import { Shipment } from '@/types'; -import { useEffect, useState } from 'react'; -import AuditTimeline from './AuditTimeline'; - -interface AuditChange { - field: string; - field_name: string; - old_value: unknown; - new_value: unknown; -} - -interface AuditEntry { - id: number; - event: string; - auditable_type?: string; - auditable_id?: number; - entity_type?: string; - entity_name?: string; - user: { - id: number; - name: string; - email: string; - } | null; - old_values: Record; - new_values: Record; - changes: AuditChange[]; - created_at: string; - created_at_human: string; - ip_address?: string; - user_agent?: string; -} +import AuditHistory from './AuditHistory'; interface ShipmentAuditHistoryProps { shipment: Shipment; @@ -38,52 +8,11 @@ interface ShipmentAuditHistoryProps { export default function ShipmentAuditHistory({ shipment, }: ShipmentAuditHistoryProps) { - const [audits, setAudits] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - const fetchAudits = async () => { - try { - setLoading(true); - const response = await fetch( - route('shipments.audit-history', shipment.id), - ); - - if (!response.ok) { - throw new Error('Failed to fetch audit history'); - } - - const data = await response.json(); - setAudits(data.audits || []); - } catch (err) { - setError( - err instanceof Error ? err.message : 'An error occurred', - ); - } finally { - setLoading(false); - } - }; - - if (shipment.id) { - fetchAudits(); - } - }, [shipment.id]); - - if (error) { - return ( - - -
-
- Error loading audit history -
-
{error}
-
-
-
- ); - } - - return ; + return ( + + ); } diff --git a/resources/js/Components/Audit/types.ts b/resources/js/Components/Audit/types.ts new file mode 100644 index 00000000..69407dda --- /dev/null +++ b/resources/js/Components/Audit/types.ts @@ -0,0 +1,27 @@ +export interface AuditChange { + field: string; + field_name: string; + old_value: unknown; + new_value: unknown; +} + +export interface AuditEntry { + id: number; + event: string; + auditable_type?: string; + auditable_id?: number; + entity_type?: string; + entity_name?: string; + user: { + id: number; + name: string; + email: string; + } | null; + old_values: Record; + new_values: Record; + changes: AuditChange[]; + created_at: string; + created_at_human: string; + ip_address?: string; + user_agent?: string; +}