diff --git a/app/Console/Commands/DataTableMakeCommand.php b/app/Console/Commands/DataTableMakeCommand.php new file mode 100644 index 0000000..2d48b9a --- /dev/null +++ b/app/Console/Commands/DataTableMakeCommand.php @@ -0,0 +1,193 @@ +files->get($this->getStub()); + + $domain = ucfirst($this->argument('domain')); + $className = class_basename(str_replace('/', '\\', $this->getNameInput())); + + $modelOption = $this->option('model') ?? Str::replaceLast('DataTable', '', $className); + $modelData = $this->resolveModel($modelOption, $domain); + + $modelClass = $modelData['class']; + $modelVariable = Str::camel($modelClass); + $tableId = Str::kebab($modelClass).'-table'; + + $replacements = [ + '{{ namespace }}' => $this->getNamespace($name), + '{{ class }}' => $className, + '{{ modelImport }}' => "use {$modelData['full']};\n", + '{{ model }}' => $modelClass, + '{{ modelVariable }}' => $modelVariable, + '{{ tableId }}' => $tableId, + ]; + + return str_replace(array_keys($replacements), array_values($replacements), $stub); + } + + /** + * Resolve model data. + */ + protected function resolveModel(string $modelOption, string $domain): array + { + if (Str::contains($modelOption, ['\\', '/'])) { + if (Str::startsWith(str_replace('/', '\\', $modelOption), 'App\\')) { + $full = str_replace('/', '\\', $modelOption); + $class = class_basename($full); + } else { + $parts = explode('/', str_replace('\\', '/', $modelOption)); + $targetDomain = ucfirst($parts[0]); + $targetName = implode('\\', array_map('ucfirst', array_slice($parts, 1))); + $full = "App\\Domains\\{$targetDomain}\\Models\\{$targetName}"; + $class = class_basename($full); + } + } else { + $full = "App\\Domains\\{$domain}\\Models\\".ucfirst($modelOption); + $class = ucfirst($modelOption); + } + + return [ + 'full' => $full, + 'class' => $class, + ]; + } + + /** + * Get the destination class path. + * + * @param string $name + */ + protected function getPath($name): string + { + $name = Str::replaceFirst($this->rootNamespace(), '', $name); + + return $this->laravel->basePath().'/app/'.str_replace('\\', '/', $name).'.php'; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + */ + protected function getDefaultNamespace($rootNamespace): string + { + $domain = ucfirst($this->argument('domain')); + + return $rootNamespace."\\Http\\DataTables\\{$domain}"; + } + + /** + * Get the stub file for the generator. + */ + protected function getStub(): string + { + return app_path('Console/stubs/domain-datatable/datatable.stub'); + } + + /** + * Parse the name and format according to the root namespace. + * + * @param string $name + * @return string + */ + protected function qualifyClass($name) + { + $name = ltrim($name, '\\/'); + + $rootNamespace = $this->rootNamespace(); + + if (Str::startsWith($name, $rootNamespace)) { + return $name; + } + + return $this->qualifyClass( + $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name + ); + } + + /** + * Execute the console command. + * + * @return bool|null + */ + public function handle() + { + $status = GeneratorCommand::handle(); + + if ($status !== false) { + $this->createView(); + } + + return $status; + } + + protected function createView(): void + { + $domain = ucfirst($this->argument('domain')); + $className = class_basename(str_replace('/', '\\', $this->getNameInput())); + $capability = Str::replaceLast('DataTable', '', $className); + + $directory = resource_path('views/pages/'.Str::lower($domain).'/'.Str::lower(Str::plural($capability))); + $path = "{$directory}/index.blade.php"; + + if ($this->files->exists($path)) { + $this->components->warn("View already exists: [{$path}]"); + + return; + } + + $this->files->ensureDirectoryExists($directory); + + $stub = $this->files->get(app_path('Console/stubs/domain-datatable/datatable-view.stub')); + + $modelOption = $this->option('model') ?? $capability; + $modelData = $this->resolveModel($modelOption, $domain); + + $replacements = [ + '{{ domain }}' => $domain, + '{{ domainLower }}' => Str::lower($domain), + '{{ domainDot }}' => Str::lower($domain), + '{{ capabilityDot }}' => Str::lower(Str::plural($capability)), + '{{ model }}' => $modelData['class'], + '{{ modelFull }}' => $modelData['full'], + '{{ modelVariable }}' => Str::camel($modelData['class']), + ]; + + $content = str_replace(array_keys($replacements), array_values($replacements), $stub); + + $this->files->put($path, $content); + + $this->components->info('View created: resources/views/pages/'.Str::lower($domain).'/'.Str::lower(Str::plural($capability)).'/index.blade.php'); + } +} diff --git a/app/Console/Commands/DomainMakeCommand.php b/app/Console/Commands/DomainMakeCommand.php index fa6bc36..109633b 100644 --- a/app/Console/Commands/DomainMakeCommand.php +++ b/app/Console/Commands/DomainMakeCommand.php @@ -14,6 +14,8 @@ class DomainMakeCommand extends Command {name : Class name, supports sub-paths e.g. Backup/DeleteBackup} {--factory : Also generate a factory (model only)} {--migration : Also generate a migration (model only)} + {--policy : Also generate a policy (model only)} + {--all : Generate a factory, migration, and policy (model only)} {--model= : Associate the export with a model}'; protected $description = 'Generate a file directly into the domain structure (app/Domains/)'; @@ -35,7 +37,7 @@ class DomainMakeCommand extends Command 'relationship-provider' => 'Providers', 'view-provider' => 'Providers', 'export' => 'Exports', - // Integration layer — files live under Integration// + 'integration' => 'Integration', 'mapper' => 'Integration/Mappers', 'mailable' => 'Mail', ]; @@ -49,7 +51,7 @@ class DomainMakeCommand extends Command { $type = strtolower($this->argument('type')); $domain = ucfirst($this->argument('domain')); - $name = $this->argument('name'); // may contain sub-path, e.g. Backup/DeleteBackup + $name = $this->argument('name'); if (! isset($this->types[$type])) { $this->components->error("Unknown type [{$type}]. Supported: ".implode(', ', array_keys($this->types))); @@ -57,24 +59,19 @@ class DomainMakeCommand extends Command return self::FAILURE; } - $subDir = $this->types[$type]; $className = class_basename(str_replace('/', '\\', $name)); $subPath = str_contains($name, '/') ? dirname($name) : null; - // ── Integration / Mapper special handling ───────────────────────────── - // Automatically append the 'DataMapper' suffix when the developer omits it, - // keeping the class name consistent with the DataPayloadMapper contract. if ($type === 'mapper' && ! str_ends_with($className, 'DataMapper')) { $className .= 'DataMapper'; } - // The $subDir for 'mapper' already encodes the full Integration/Mappers - // nested path, so we must not double-nest an additional subPath beneath it. - // Extra sub-path segments are intentionally ignored for the mapper type. - $relativeDir = ($type === 'mapper') - ? "Domains/{$domain}/{$subDir}" - : "Domains/{$domain}/{$subDir}".($subPath ? "/{$subPath}" : ''); - // ───────────────────────────────────────────────────────────────────── + $subDir = $this->types[$type]; + $relativeDir = "Domains/{$domain}/{$subDir}"; + + if ($type !== 'mapper' && $subPath) { + $relativeDir .= "/{$subPath}"; + } $namespace = 'App\\'.str_replace('/', '\\', $relativeDir); $path = app_path("{$relativeDir}/{$className}.php"); @@ -90,16 +87,31 @@ class DomainMakeCommand extends Command $this->components->info("File [{$path}] created successfully."); - if ($type === 'model' && $this->option('factory')) { + if ($type === 'model') { + $this->handleModelExtra($domain, $className, $namespace); + } + + return self::SUCCESS; + } + + protected function handleModelExtra(string $domain, string $className, string $namespace): void + { + if ($this->option('factory') || $this->option('all')) { $this->createFactory($domain, $className, $namespace); } - if ($type === 'model' && $this->option('migration')) { + if ($this->option('migration') || $this->option('all')) { $table = Str::snake(Str::pluralStudly($className)); $this->call('make:migration', ['name' => "create_{$table}_table"]); } - return self::SUCCESS; + if ($this->option('policy') || $this->option('all')) { + $this->call('domain:make', [ + 'type' => 'policy', + 'domain' => $domain, + 'name' => "{$className}Policy", + ]); + } } // ─── Stubs ──────────────────────────────────────────────────────────────── @@ -119,39 +131,54 @@ class DomainMakeCommand extends Command $replacements = [ '{{ namespace }}' => $namespace, '{{ class }}' => $name, + '{{ factory }}' => '', ]; - if ($type === 'model') { - $replacements['{{ factoryImport }}'] = $this->option('factory') - ? "\nuse Database\\Factories\\{$domain}\\{$name}Factory;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;" - : ''; - $replacements['{{ factoryMethod }}'] = $this->option('factory') - ? "\n protected static function newFactory(): Factory\n {\n return {$name}Factory::new();\n }" - : ''; - } + $replacements = match ($type) { + 'model' => array_merge($replacements, $this->getModelReplacements($domain, $name)), + 'export' => array_merge($replacements, $this->getExportReplacements($domain)), + default => $replacements, + }; + + return str_replace(array_keys($replacements), array_values($replacements), $stub); + } + + protected function getModelReplacements(string $domain, string $name): array + { + $hasFactory = $this->option('factory') || $this->option('all'); - if ($type === 'export') { - $modelOption = $this->option('model'); - $modelImport = ''; - $queryBody = ' // return YourModel::query();'; + return [ + '{{ factoryImport }}' => $hasFactory + ? "\nuse Database\\Factories\\{$domain}\\{$name}Factory;" + : '', + '{{ factory }}' => $hasFactory + ? "#[UseFactory({$name}Factory::class)]" + : '', + ]; + } - if ($modelOption) { - $modelData = $this->resolveModel($modelOption, $domain); - $modelImport = "use {$modelData['full']};\n"; - $modelClass = $modelData['class']; - $queryBody = <<option('model'); + $modelImport = ''; + $queryBody = ' // return YourModel::query();'; + + if ($modelOption) { + $modelData = $this->resolveModel($modelOption, $domain); + $modelImport = "use {$modelData['full']};\n"; + $modelClass = $modelData['class']; + $queryBody = <<with('profile') // CRITICAL: Eager load any relations used in map() // ->when(isset(\$this->filters['status']), fn(Builder \$q) => \$q->where('status', \$this->filters['status'])) ; PHP; - } - - $replacements['{{ modelImport }}'] = $modelImport; - $replacements['{{ queryBody }}'] = $queryBody; } - return str_replace(array_keys($replacements), array_values($replacements), $stub); + return [ + '{{ modelImport }}' => $modelImport, + '{{ queryBody }}' => $queryBody, + ]; } protected function resolveModel(string $modelOption, string $domain): array @@ -180,11 +207,8 @@ PHP; protected function createFactory(string $domain, string $name, string $modelNamespace): void { - $factoryNamespace = "Database\\Factories\\{$domain}"; $factoryPath = database_path("factories/{$domain}/{$name}Factory.php"); - $this->files->ensureDirectoryExists(dirname($factoryPath)); - if ($this->files->exists($factoryPath)) { $this->components->warn("Factory already exists: [{$factoryPath}]"); @@ -196,10 +220,11 @@ PHP; $stub = str_replace( ['{{ factoryNamespace }}', '{{ modelNamespace }}', '{{ class }}'], - [$factoryNamespace, $modelNamespace, $name], + ["Database\\Factories\\{$domain}", $modelNamespace, $name], $stub ); + $this->files->ensureDirectoryExists(dirname($factoryPath)); $this->files->put($factoryPath, $stub); $this->components->info("Factory [database/factories/{$domain}/{$name}Factory.php] created successfully."); diff --git a/app/Console/Commands/PageMakeCommand.php b/app/Console/Commands/PageMakeCommand.php new file mode 100644 index 0000000..33bf04d --- /dev/null +++ b/app/Console/Commands/PageMakeCommand.php @@ -0,0 +1,90 @@ +argument('domain')); + $capability = strtolower($this->argument('capability')); + $name = $this->argument('name'); + $isModal = $this->option('modal'); + + $directory = resource_path("views/pages/{$domain}/{$capability}"); + + if ($isModal) { + return $this->handleModal($directory, $name); + } + + $path = "{$directory}/{$name}.blade.php"; + + if ($this->files->exists($path)) { + $this->components->error("File already exists: [{$path}]"); + + return self::FAILURE; + } + + $this->files->ensureDirectoryExists($directory); + + $stubPath = app_path('Console/stubs/domain-make/page.stub'); + $stub = $this->files->get($stubPath); + + $this->files->put($path, $stub); + + $this->components->info("Page created: resources/views/pages/{$domain}/{$capability}/{$name}.blade.php"); + + return self::SUCCESS; + } + + protected function handleModal(string $directory, string $name): int + { + $modalName = Str::kebab($name); + if (! str_ends_with($modalName, '-modal')) { + $modalName .= '-modal'; + } + + $modalDir = "{$directory}/⚡{$modalName}"; + + if ($this->files->exists($modalDir)) { + $this->components->error("Modal directory already exists: [{$modalDir}]"); + + return self::FAILURE; + } + + $this->files->ensureDirectoryExists($modalDir); + + $modelVariable = Str::camel(Str::before($modalName, '-modal')); + + // Class + $classStub = $this->files->get(app_path('Console/stubs/domain-make/page-modal-class.stub')); + $classContent = str_replace('{{ modelVariable }}', $modelVariable, $classStub); + $this->files->put("{$modalDir}/{$modalName}.php", $classContent); + + // View + $viewStub = $this->files->get(app_path('Console/stubs/domain-make/page-modal-view.stub')); + $viewContent = str_replace('{{ modalId }}', $modalName, $viewStub); + $this->files->put("{$modalDir}/{$modalName}.blade.php", $viewContent); + + $this->components->info('Livewire Modal created in: resources/views/pages/...'."/⚡{$modalName}"); + + return self::SUCCESS; + } +} diff --git a/app/Console/stubs/domain-datatable/datatable-view.stub b/app/Console/stubs/domain-datatable/datatable-view.stub new file mode 100644 index 0000000..759c607 --- /dev/null +++ b/app/Console/stubs/domain-datatable/datatable-view.stub @@ -0,0 +1,18 @@ + + + {{ $dataTable->table() }} + + + + + + + @push('page-scripts') + @vite(['resources/js/plugin/datatables.js', 'resources/js/plugin/select2.js']) + {{ $dataTable->scripts(attributes: ['type' => 'module']) }} + @endpush + diff --git a/app/Console/stubs/domain-datatable/datatable.stub b/app/Console/stubs/domain-datatable/datatable.stub new file mode 100644 index 0000000..424295a --- /dev/null +++ b/app/Console/stubs/domain-datatable/datatable.stub @@ -0,0 +1,125 @@ + $query Results from query() method. + */ + public function dataTable(QueryBuilder $query): EloquentDataTable + { + return (new EloquentDataTable($query)) + ->addColumn( + 'action', + fn ({{ model }} ${{ modelVariable }}) => view('components.datatables.action-button', [ + 'view' => [ + 'modal' => '{{ modelVariable }}-view-modal', + 'permission' => auth()->user()->can('view', ${{ modelVariable }}), + ], + 'edit' => [ + 'modal' => '{{ modelVariable }}-form-modal', + 'permission' => auth()->user()->can('update', ${{ modelVariable }}), + ], + 'delete' => [ + 'url' => null, + 'title' => __('ui/button.delete'), + 'permission' => auth()->user()->can('delete', ${{ modelVariable }}), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.{{ modelVariable }}')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.{{ modelVariable }}')]), + ], + 'table_name' => '{{ tableId }}', + 'id' => ${{ modelVariable }}->ulid, + ]) + ) + ->addIndexColumn(); + } + + /** + * Get the query source of dataTable. + * + * @return QueryBuilder<{{ model }}> + */ + public function query({{ model }} $model): QueryBuilder + { + return $model->newQuery(); + } + + /** + * Optional method if you want to use the html builder. + */ + public function html(): HtmlBuilder + { + return $this->builder() + ->setTableId('{{ tableId }}') + ->columns($this->getColumns()) + ->minifiedAjax() + ->orderBy(1) + ->layout([ + 'topStart' => [ + 'className' => 'col-md-auto me-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-start align-items-center align-items-md-start gap-1', + 'features' => ['buttons', 'pageLength'], + ], + 'topEnd' => [ + 'className' => 'col-md-auto ms-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-end align-items-center align-items-md-start gap-1', + 'features' => ['search'], + ], + + 'bottomStart' => 'info', + 'bottomEnd' => 'paging', + ]) + ->parameters([ + 'language' => [ + 'search' => '', + 'searchPlaceholder' => __('ui/button.lookup'), + ], + ]) + ->buttons([ + Button::make('add') + ->action('$("#{{ modelVariable }}-form-modal").modal("show");') + ->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) + ->addClass('btn-sm'), + Button::make('reload') + ->text(svg('tabler-reload', ['width' => 16, 'height' => 16])->toHtml()) + ->addClass('btn-sm'), + ]); + } + + /** + * Get the dataTable columns definition. + */ + public function getColumns(): array + { + return [ + Column::computed('DT_RowIndex') + ->title('#') + ->searchable(false) + ->orderable(false), + Column::make('created_at') + ->title(__('ui/label.created_at')), + Column::computed('action') + ->title(__('ui/label.actions')) + ->exportable(false) + ->printable(false) + ->width(60) + ->addClass('text-center'), + ]; + } + + /** + * Get the filename for export. + */ + protected function filename(): string + { + return '{{ class }}_' . date('YmdHis'); + } +} diff --git a/app/Console/stubs/domain-make/integration.stub b/app/Console/stubs/domain-make/integration.stub new file mode 100644 index 0000000..c7dc359 --- /dev/null +++ b/app/Console/stubs/domain-make/integration.stub @@ -0,0 +1,11 @@ +id = $id; + $this->mode = 'update'; + // $this->form->fill($this->model->only(['name'])); + } + + public function hide(): void + { + // $this->form->reset(); + $this->reset('id', 'mode'); + } +}; diff --git a/app/Console/stubs/domain-make/page-modal-view.stub b/app/Console/stubs/domain-make/page-modal-view.stub new file mode 100644 index 0000000..06df847 --- /dev/null +++ b/app/Console/stubs/domain-make/page-modal-view.stub @@ -0,0 +1,11 @@ + + +
+ {{-- Form Fields --}} +
+ + + + + +
diff --git a/app/Console/stubs/domain-make/page.stub b/app/Console/stubs/domain-make/page.stub new file mode 100644 index 0000000..7b01723 --- /dev/null +++ b/app/Console/stubs/domain-make/page.stub @@ -0,0 +1,5 @@ + + + {{-- Page Content --}} + + diff --git a/app/Console/stubs/domain-make/policy.stub b/app/Console/stubs/domain-make/policy.stub index a703565..1bb6f6c 100644 --- a/app/Console/stubs/domain-make/policy.stub +++ b/app/Console/stubs/domain-make/policy.stub @@ -3,9 +3,12 @@ namespace {{ namespace }}; use App\Domains\Identity\Models\User; +use Illuminate\Auth\Access\HandlesAuthorization; class {{ class }} { + use HandlesAuthorization; + public function viewAny(User $user): bool { return false; @@ -30,4 +33,4 @@ class {{ class }} { return false; } -} \ No newline at end of file +} diff --git a/app/Domains/Academic/Providers/RelationshipServiceProvider.php b/app/Domains/Academic/Providers/RelationshipServiceProvider.php index 4de18cf..d0c982f 100644 --- a/app/Domains/Academic/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Academic/Providers/RelationshipServiceProvider.php @@ -17,7 +17,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/Account/Enums/GenderOption.php b/app/Domains/Account/Enums/GenderOption.php index 8212202..bd5c0d6 100644 --- a/app/Domains/Account/Enums/GenderOption.php +++ b/app/Domains/Account/Enums/GenderOption.php @@ -2,12 +2,17 @@ namespace App\Domains\Account\Enums; +use App\Domains\System\Traits\Enum\HasPredicateMethod; use App\UI\Enums\Concerns\InteractsWithLabels; use App\UI\Enums\Contracts\HasLabel; -use App\UI\Enums\Contracts\HasUiBadge; -enum GenderOption: string implements HasLabel, HasUiBadge +/* + * @method bool isMale() + * @method bool isFemale() + */ +enum GenderOption: string implements HasLabel { + use HasPredicateMethod; use InteractsWithLabels; case MALE = 'male'; @@ -20,12 +25,4 @@ enum GenderOption: string implements HasLabel, HasUiBadge self::FEMALE->label() => self::FEMALE, }; } - - public function variant(): string - { - return match ($this) { - self::MALE => 'primary', - self::FEMALE => 'secondary', - }; - } } diff --git a/app/Domains/Account/Models/Profile.php b/app/Domains/Account/Models/Profile.php index bac9043..a2b6944 100644 --- a/app/Domains/Account/Models/Profile.php +++ b/app/Domains/Account/Models/Profile.php @@ -6,22 +6,17 @@ use App\Domains\Account\Enums\GenderOption; use App\Domains\Identity\Models\User; use Database\Factories\Account\ProfileFactory; use Illuminate\Database\Eloquent\Attributes\Fillable; -use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Database\Eloquent\Attributes\UseFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; #[Fillable(['user_id', 'gender', 'date_of_birth', 'phone_number'])] +#[UseFactory(ProfileFactory::class)] class Profile extends Model { - /** @use HasFactory */ use HasFactory; - protected static function newFactory(): Factory - { - return ProfileFactory::new(); - } - protected function casts(): array { return [ diff --git a/app/Domains/Account/Providers/RelationshipServiceProvider.php b/app/Domains/Account/Providers/RelationshipServiceProvider.php index da85b67..be0b7ba 100644 --- a/app/Domains/Account/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Account/Providers/RelationshipServiceProvider.php @@ -15,7 +15,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/Admission/Models/FeeRate.php b/app/Domains/Admission/Models/FeeRate.php index 933c8da..4d06505 100644 --- a/app/Domains/Admission/Models/FeeRate.php +++ b/app/Domains/Admission/Models/FeeRate.php @@ -3,6 +3,7 @@ namespace App\Domains\Admission\Models; use App\Domains\Admission\Policies\FeeRatePolicy; +use App\Domains\Finance\Casts\MoneyCurrency; use Database\Factories\Admission\FeeRateFactory; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\UsePolicy; @@ -25,6 +26,10 @@ class FeeRate extends Model use HasFactory; use HasUlids; + protected $casts = [ + 'amount' => MoneyCurrency::class, + ]; + public function uniqueIds(): array { return ['ulid']; diff --git a/app/Domains/Admission/Providers/RelationshipServiceProvider.php b/app/Domains/Admission/Providers/RelationshipServiceProvider.php index 7d2d710..6a8a4df 100644 --- a/app/Domains/Admission/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Admission/Providers/RelationshipServiceProvider.php @@ -13,7 +13,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/Channel/Actions/Api/AssignEndpointUrl.php b/app/Domains/Channel/Actions/Api/AssignEndpointUrl.php new file mode 100644 index 0000000..b278256 --- /dev/null +++ b/app/Domains/Channel/Actions/Api/AssignEndpointUrl.php @@ -0,0 +1,29 @@ + $endpoint instanceof EndpointUrlDTO, $endpointToSave); + if (in_array(false, $validateArrayDTO)) { + throw new \Exception(sprintf('Invalid parameter. to use this action, the $endpointToSave must be an array of %s', EndpointUrlDTO::class)); + } + + $toSave = array_map(fn(EndpointUrlDTO $endpoint) => [ + 'client_id' => $endpoint->clientId, + 'key' => $endpoint->field, + 'value' => $endpoint->endpointUrl + ], $endpointToSave); + ApiEndpoint::upsert($toSave, ['client_id', 'key']); + } +} diff --git a/app/Domains/Channel/Actions/AppProvisioning/DeauthorizConsumerApp.php b/app/Domains/Channel/Actions/AppProvisioning/DeauthorizConsumerApp.php deleted file mode 100644 index 8fd1bdd..0000000 --- a/app/Domains/Channel/Actions/AppProvisioning/DeauthorizConsumerApp.php +++ /dev/null @@ -1,13 +0,0 @@ -update([ + 'webhook' => $dto->webhook_url, + 'auth_type' => $dto->auth_type, + 'credentials' => $dto->credentials, + ]); + } +} diff --git a/app/Domains/Channel/Actions/AppProvisioning/ProvisionConsumerApp.php b/app/Domains/Channel/Actions/AppProvisioning/ProvisionConsumerApp.php index c09d62f..754a11d 100644 --- a/app/Domains/Channel/Actions/AppProvisioning/ProvisionConsumerApp.php +++ b/app/Domains/Channel/Actions/AppProvisioning/ProvisionConsumerApp.php @@ -11,8 +11,10 @@ class ProvisionConsumerApp { Client::create([ 'name' => $dto->name, - 'code' => $dto->code, - 'url' => $dto->url, + 'domain' => $dto->domain, + 'webhook' => $dto->webhook_url, + 'auth_type' => $dto->auth_type, + 'credentials' => $dto->credentials, 'secret' => encrypt(uuid_create()), ]); } diff --git a/app/Domains/Channel/DTOs/Api/EndpointUrlDTO.php b/app/Domains/Channel/DTOs/Api/EndpointUrlDTO.php new file mode 100644 index 0000000..4013b7c --- /dev/null +++ b/app/Domains/Channel/DTOs/Api/EndpointUrlDTO.php @@ -0,0 +1,14 @@ + $credentials + */ public function __construct( public string $name, - public string $code, - public string $url, + public string $domain, + public string $webhook_url, + public AuthType $auth_type, + public array $credentials, ) {} } diff --git a/app/Domains/Channel/Enums/Api/ApiType.php b/app/Domains/Channel/Enums/Api/ApiType.php new file mode 100644 index 0000000..d3c1a0c --- /dev/null +++ b/app/Domains/Channel/Enums/Api/ApiType.php @@ -0,0 +1,63 @@ +default('-'); + } + + public function default(): mixed + { + return $this->schema()->default; + } + + public function inputAttributes(): array + { + return array_merge($this->schema()->attributes, [ + 'label' => $this->label(), + 'options' => $this->schema()->type->isSelect() ? $this->schema()->options : '', + ]); + } + + public static function section(): array + { + return [ + [ + __('domains/system/pages.api.sections.academic') => [ + self::FACULTY, + self::STUDY_PROGRAM, + self::TERM, + ], + ], + [ + __('domains/system/pages.api.sections.admission') => [ + self::ACADEMIC_PROGRAM, + self::ADMISSION_TRACK, + self::ADMISSION_SCHEDULE, + self::FEE_TYPE, + ], + ], + ]; + } +} diff --git a/app/Domains/Channel/Enums/Client/AuthType.php b/app/Domains/Channel/Enums/Client/AuthType.php new file mode 100644 index 0000000..ffb28a4 --- /dev/null +++ b/app/Domains/Channel/Enums/Client/AuthType.php @@ -0,0 +1,17 @@ + ApiType::class, + ]; + + public function client(): BelongsTo + { + return $this->belongsTo(Client::class); + } +} diff --git a/app/Domains/Channel/Models/Client.php b/app/Domains/Channel/Models/Client.php index a85d152..e5dd9c4 100644 --- a/app/Domains/Channel/Models/Client.php +++ b/app/Domains/Channel/Models/Client.php @@ -2,6 +2,7 @@ namespace App\Domains\Channel\Models; +use App\Domains\Channel\Enums\Client\AuthType; use App\Domains\Channel\Policies\ClientPolicy; use Database\Factories\Channel\ClientFactory; use Illuminate\Database\Eloquent\Attributes\Fillable; @@ -11,7 +12,7 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -#[Fillable(['name', 'url', 'code', 'secret'])] +#[Fillable(['name', 'domain', 'webhook', 'auth_type', 'credentials', 'secret'])] #[UsePolicy(ClientPolicy::class)] class Client extends Model { @@ -20,6 +21,8 @@ class Client extends Model protected $casts = [ 'secret' => 'encrypted', + 'auth_type' => AuthType::class, + 'credentials' => 'encrypted:array', ]; protected static function newFactory(): Factory diff --git a/app/Domains/Channel/Providers/RelationshipServiceProvider.php b/app/Domains/Channel/Providers/RelationshipServiceProvider.php index db337be..929e097 100644 --- a/app/Domains/Channel/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Channel/Providers/RelationshipServiceProvider.php @@ -16,7 +16,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/Finance/Casts/MoneyCurrency.php b/app/Domains/Finance/Casts/MoneyCurrency.php index 2a3c98d..e16621b 100644 --- a/app/Domains/Finance/Casts/MoneyCurrency.php +++ b/app/Domains/Finance/Casts/MoneyCurrency.php @@ -15,7 +15,7 @@ class MoneyCurrency implements CastsAttributes return null; } - return new Money((int) $value); + return new Money((float) $value); } public function set(Model $model, string $key, mixed $value, array $attributes): ?float @@ -25,7 +25,7 @@ class MoneyCurrency implements CastsAttributes } if ($value instanceof Money) { - return $value->amount; + return $value->toFloat(); } if (is_numeric($value)) { diff --git a/app/Domains/Finance/Providers/RelationshipServiceProvider.php b/app/Domains/Finance/Providers/RelationshipServiceProvider.php index 52b2e72..73894aa 100644 --- a/app/Domains/Finance/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Finance/Providers/RelationshipServiceProvider.php @@ -13,7 +13,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/Finance/Support/ValueObjects/Money.php b/app/Domains/Finance/Support/ValueObjects/Money.php index 38d13fc..9fd1e2e 100644 --- a/app/Domains/Finance/Support/ValueObjects/Money.php +++ b/app/Domains/Finance/Support/ValueObjects/Money.php @@ -8,7 +8,7 @@ use Stringable; class Money implements Stringable { - public function __construct(public float $amount) + public function __construct(private readonly float $amount) { if ($this->amount < 0) { throw new InvalidArgumentException('Money cannot be negative.'); @@ -16,7 +16,7 @@ class Money implements Stringable } /** - * Format the bytes into a human-readable string. + * Format the money into a selected currency string. */ public function format(string $currency = 'IDR'): string { @@ -25,6 +25,11 @@ class Money implements Stringable return $format->formatCurrency($this->amount, $currency); } + public function toFloat(): float + { + return $this->amount; + } + /** * Automatically format when echoed in Blade (e.g., {{ $model->amount }}). */ diff --git a/app/Domains/Identity/Actions/AccessControl/DefineSystemRole.php b/app/Domains/Identity/Actions/AccessControl/DefineSystemRole.php deleted file mode 100644 index 6ddc1ae..0000000 --- a/app/Domains/Identity/Actions/AccessControl/DefineSystemRole.php +++ /dev/null @@ -1,26 +0,0 @@ - $dto->name, - ]); - $role->syncPermissions($dto->permissions); - - return true; - }); - } -} diff --git a/app/Domains/Identity/Actions/AccessControl/DeleteSystemRole.php b/app/Domains/Identity/Actions/AccessControl/DeleteSystemRole.php deleted file mode 100644 index 1083a52..0000000 --- a/app/Domains/Identity/Actions/AccessControl/DeleteSystemRole.php +++ /dev/null @@ -1,26 +0,0 @@ -name, [RoleType::ADMIN->value, RoleType::SYSTEM_ADMIN->value])) { - throw new Exception(__('domains/identity/messages.exceptions.cannot_remove_system_role')); - } - - if ($role->users()->exists()) { - throw new Exception(__('domains/identity/messages.exceptions.role_has_users')); - } - } -} diff --git a/app/Domains/Identity/Actions/Governance/DeleteUser.php b/app/Domains/Identity/Actions/Governance/DeleteUser.php deleted file mode 100644 index 8b8c17d..0000000 --- a/app/Domains/Identity/Actions/Governance/DeleteUser.php +++ /dev/null @@ -1,22 +0,0 @@ -status->isActive()) { - $this->suspendUser->execute($user); - } else { - $this->purgeUser->execute($user); - } - } -} diff --git a/app/Domains/Identity/Enums/RoleType.php b/app/Domains/Identity/Enums/RoleType.php index 23309c6..4e41c67 100644 --- a/app/Domains/Identity/Enums/RoleType.php +++ b/app/Domains/Identity/Enums/RoleType.php @@ -34,24 +34,23 @@ enum RoleType: string 'roles' => [self::USER], ], - ...self::generatePolicy('role', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('user', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('faculty', [self::SYSTEM_ADMIN, self::ADMIN]), ...self::generatePolicy('study-program', [self::SYSTEM_ADMIN, self::ADMIN]), ...self::generatePolicy('term', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('client', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('admission-track', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('academic-program', [self::SYSTEM_ADMIN, self::ADMIN]), ...self::generatePolicy('admission-schedule', [self::SYSTEM_ADMIN, self::ADMIN]), + ...self::generatePolicy('academic-program', [self::SYSTEM_ADMIN, self::ADMIN]), ...self::generatePolicy('fee-type', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('chart-of-account', [self::SYSTEM_ADMIN, self::ADMIN]), + ...self::generatePolicy('client', [self::SYSTEM_ADMIN, self::ADMIN]), + ...self::generatePolicy('invoice', [self::SYSTEM_ADMIN, self::ADMIN]), ...self::generatePolicy('product-mapping', [self::SYSTEM_ADMIN, self::ADMIN]), - ...self::generatePolicy('payment', [self::SYSTEM_ADMIN, self::ADMIN]), + ...self::generatePolicy('chart-of-account', [self::SYSTEM_ADMIN, self::ADMIN]), + + ...self::generatePolicy('role', [self::SYSTEM_ADMIN, self::ADMIN]), + ...self::generatePolicy('user', [self::SYSTEM_ADMIN, self::ADMIN]), // System Setting [ @@ -61,6 +60,13 @@ enum RoleType: string 'guard_name' => 'web', 'roles' => [self::SYSTEM_ADMIN, self::ADMIN], ], + [ + 'name' => 'system-setting.api', + 'description' => 'permissions.system-setting.api', + 'group' => 'system-setting', + 'guard_name' => 'web', + 'roles' => [self::SYSTEM_ADMIN, self::ADMIN], + ], // System Backup [ diff --git a/app/Domains/Identity/Enums/UserSettingKey.php b/app/Domains/Identity/Enums/UserSettingKey.php index d38e90d..e8a7778 100644 --- a/app/Domains/Identity/Enums/UserSettingKey.php +++ b/app/Domains/Identity/Enums/UserSettingKey.php @@ -2,72 +2,48 @@ namespace App\Domains\Identity\Enums; +use App\UI\Enums\Concerns\InteractsWithLabels; +use App\UI\Enums\Contracts\HasLabel; +use App\UI\Enums\Contracts\HasSchema; +use App\UI\Enums\InputType; +use App\UI\Support\Settings\SettingSchema; use Illuminate\Validation\Rule; -enum UserSettingKey: string +enum UserSettingKey: string implements HasLabel, HasSchema { + use InteractsWithLabels; + case NOTIFICATION = 'notification'; case LANGUAGE = 'language'; case TIMEZONE = 'timezone'; - public function label(): string - { - return __("domains/account/enum.user_settings.{$this->value}"); - } - - public static function effect(string $settingKey, string|int $value): void - { - match ($settingKey) { - self::LANGUAGE->value => app()->setLocale($value), - self::TIMEZONE->value => date_default_timezone_set($value), - default => null, - }; - } - - public function default(): mixed - { - return match ($this) { - self::NOTIFICATION => 0, - self::LANGUAGE => 'en', - self::TIMEZONE => 'UTC', - }; - } - - public function type(): string + public function schema(): SettingSchema { - return match ($this) { - self::NOTIFICATION, - self::LANGUAGE, - self::TIMEZONE => 'option', - }; - } - - public function options(): array - { - return match ($this) { + $options = match ($this) { self::LANGUAGE => [ - 'en' => __('domains/account/enum.user_settings.options.language.en'), - 'id' => __('domains/account/enum.user_settings.options.language.id'), + 'en' => __('domains/identity/enum.user_setting_key.options.language.en'), + 'id' => __('domains/identity/enum.user_setting_key.options.language.id'), ], self::TIMEZONE => [ - 'UTC' => 'UTC', - 'Asia/Jakarta' => 'Asia/Jakarta', - 'Asia/Makassar' => 'Asia/Makassar', - 'Asia/Jayapura' => 'Asia/Jayapura', + 'UTC' => __('domains/identity/enum.user_setting_key.options.timezone.UTC'), + 'Asia/Jakarta' => __('domains/identity/enum.user_setting_key.options.timezone.Asia/Jakarta'), + 'Asia/Makassar' => __('domains/identity/enum.user_setting_key.options.timezone.Asia/Makassar'), + 'Asia/Jayapura' => __('domains/identity/enum.user_setting_key.options.timezone.Asia/Jayapura'), ], self::NOTIFICATION => [ - 1 => __('domains/account/enum.user_settings.options.notification.on'), - 0 => __('domains/account/enum.user_settings.options.notification.off'), + 1 => __('domains/identity/enum.user_setting_key.options.notification.on'), + 0 => __('domains/identity/enum.user_setting_key.options.notification.off'), ], - default => [], }; - } - public function validation(): array - { - return [ - 'required', - Rule::in(array_keys($this->options())), - ]; + $default = match ($this) { + self::NOTIFICATION => 0, + self::LANGUAGE => 'en', + self::TIMEZONE => 'UTC', + }; + + return SettingSchema::make(InputType::SELECT, ['required', Rule::in(array_keys($options))]) + ->default($default) + ->options($options); } } diff --git a/app/Domains/Identity/Enums/UserStatus.php b/app/Domains/Identity/Enums/UserStatus.php index 863206e..9433441 100644 --- a/app/Domains/Identity/Enums/UserStatus.php +++ b/app/Domains/Identity/Enums/UserStatus.php @@ -5,8 +5,13 @@ namespace App\Domains\Identity\Enums; use App\Domains\System\Traits\Enum\HasPredicateMethod; use App\UI\Enums\Concerns\InteractsWithLabels; use App\UI\Enums\Contracts\HasLabel; +use App\UI\Enums\Contracts\HasUiBadge; -enum UserStatus: string implements HasLabel +/** + * @method bool isActive() + * @method bool isInactive() + */ +enum UserStatus: string implements HasLabel, HasUiBadge { use HasPredicateMethod; use InteractsWithLabels; @@ -14,12 +19,7 @@ enum UserStatus: string implements HasLabel case ACTIVE = 'active'; case INACTIVE = 'inactive'; - public function label(): string - { - return __('domains/identity/enum.user_status.'.$this->value); - } - - public function badge(): string + public function variant(): string { return match ($this) { self::ACTIVE => 'success', diff --git a/app/Domains/Identity/Models/User.php b/app/Domains/Identity/Models/User.php index 0f3f80f..49af524 100644 --- a/app/Domains/Identity/Models/User.php +++ b/app/Domains/Identity/Models/User.php @@ -11,9 +11,9 @@ use Database\Factories\Identity\UserFactory; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\Hidden; +use Illuminate\Database\Eloquent\Attributes\UseFactory; use Illuminate\Database\Eloquent\Attributes\UsePolicy; use Illuminate\Database\Eloquent\Concerns\HasUlids; -use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Foundation\Auth\User as Authenticatable; @@ -25,13 +25,11 @@ use Spatie\Permission\Traits\HasRoles; #[Fillable(['name', 'email', 'password', 'status', 'settings'])] #[Hidden(['password', 'remember_token'])] #[UsePolicy(UserPolicy::class)] +#[UseFactory(UserFactory::class)] class User extends Authenticatable implements Auditable, MustVerifyEmail { use HasApiTokens; - - /** @use HasFactory */ use HasFactory; - use HasFile; use HasRoles; use HasUlids; @@ -59,11 +57,6 @@ class User extends Authenticatable implements Auditable, MustVerifyEmail 'status', ]; - protected static function newFactory(): Factory - { - return UserFactory::new(); - } - public function sendPasswordResetNotification($token): void { // This overrides the default CanResetPassword trait method diff --git a/app/Domains/Identity/Providers/RelationshipServiceProvider.php b/app/Domains/Identity/Providers/RelationshipServiceProvider.php index 5694329..3c72e5e 100644 --- a/app/Domains/Identity/Providers/RelationshipServiceProvider.php +++ b/app/Domains/Identity/Providers/RelationshipServiceProvider.php @@ -15,7 +15,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/System/Actions/Backup/ArchiveSystemBackup.php b/app/Domains/System/Actions/Backup/ArchiveSystemBackup.php deleted file mode 100644 index 940e8e8..0000000 --- a/app/Domains/System/Actions/Backup/ArchiveSystemBackup.php +++ /dev/null @@ -1,24 +0,0 @@ -syncBackupCatalog->execute(); - } -} diff --git a/app/Domains/System/Actions/Backup/SystemBackup.php b/app/Domains/System/Actions/Backup/SystemBackup.php new file mode 100644 index 0000000..4992d93 --- /dev/null +++ b/app/Domains/System/Actions/Backup/SystemBackup.php @@ -0,0 +1,42 @@ +allFiles($backupName); + if (empty($files)) { + throw new Exception(__('domains/system/messages.backup.verification_error')); + } + + $latestFile = collect($files)->last(); + $fileName = $backupName.' '.basename($latestFile); + $sizeInBytes = Storage::disk($disk)->size($latestFile); + + return Backup::create([ + 'file_name' => $fileName, + 'disk' => $disk, + 'path' => $latestFile, + 'size' => $sizeInBytes, + 'type' => 'full', + ]); + } +} diff --git a/app/Domains/System/Actions/Files/PruneOrphanedFiles.php b/app/Domains/System/Actions/Files/PruneOrphanedFiles.php index bd9093f..1ffa375 100644 --- a/app/Domains/System/Actions/Files/PruneOrphanedFiles.php +++ b/app/Domains/System/Actions/Files/PruneOrphanedFiles.php @@ -35,7 +35,7 @@ class PruneOrphanedFiles $trackedFiles = File::pluck('path')->toArray(); $settingFiles = collect(SystemSettingKey::cases()) - ->filter(fn ($key) => $key->inputType() === InputType::FILE) + ->filter(fn ($key) => $key->schema()->type === InputType::FILE) ->map(fn ($key) => $this->settingQuery->get($key)) ->filter() ->toArray(); diff --git a/app/Domains/System/Actions/Settings/UpdateSettings.php b/app/Domains/System/Actions/Settings/UpdateSettings.php index fd2f34f..4266340 100644 --- a/app/Domains/System/Actions/Settings/UpdateSettings.php +++ b/app/Domains/System/Actions/Settings/UpdateSettings.php @@ -12,7 +12,7 @@ class UpdateSettings { $value = $dto->value; - if ($dto->key->isImage()) { + if ($dto->key->schema()->type->isFile()) { $currentSettings = SystemSettings::where('key', $dto->key->value)->value('value'); if ($currentSettings) { @@ -33,6 +33,6 @@ class UpdateSettings ['value' => $value], ); - cache()->forget('system_settings'); + cache()->forget(SystemSettings::$cacheName); } } diff --git a/app/Domains/System/Enums/LifecycleStatus.php b/app/Domains/System/Enums/LifecycleStatus.php index cd9bc34..b9df5a9 100644 --- a/app/Domains/System/Enums/LifecycleStatus.php +++ b/app/Domains/System/Enums/LifecycleStatus.php @@ -5,21 +5,12 @@ namespace App\Domains\System\Enums; use App\Domains\System\Traits\Enum\HasPredicateMethod; use App\UI\Enums\Concerns\InteractsWithLabels; use App\UI\Enums\Contracts\HasLabel; -use App\UI\Enums\Contracts\HasUiBadge; -enum LifecycleStatus: string implements HasLabel, HasUiBadge +enum LifecycleStatus: string implements HasLabel { use HasPredicateMethod; use InteractsWithLabels; case ACTIVE = 'active'; - case ARCHIVED = 'archived'; - - public function variant(): string - { - return match ($this) { - self::ACTIVE => 'success', - self::ARCHIVED => 'secondary', - }; - } + case INACTIVE = 'inactive'; } diff --git a/app/Domains/System/Enums/SystemSettingKey.php b/app/Domains/System/Enums/SystemSettingKey.php index 0b959e2..960c62c 100644 --- a/app/Domains/System/Enums/SystemSettingKey.php +++ b/app/Domains/System/Enums/SystemSettingKey.php @@ -2,11 +2,19 @@ namespace App\Domains\System\Enums; +use App\Domains\System\Traits\Enum\HasPredicateMethod; +use App\UI\Enums\Concerns\InteractsWithLabels; +use App\UI\Enums\Contracts\HasLabel; +use App\UI\Enums\Contracts\HasSchema; use App\UI\Enums\FileType; use App\UI\Enums\InputType; +use App\UI\Support\Settings\SettingSchema; -enum SystemSettingKey: string +enum SystemSettingKey: string implements HasLabel, HasSchema { + use HasPredicateMethod; + use InteractsWithLabels; + case WEB_NAME = 'web-name'; case WEB_DESCRIPTION = 'web-description'; case WEB_LOGO = 'web-logo'; @@ -14,117 +22,82 @@ enum SystemSettingKey: string case WEB_PHONE = 'web-phone'; case WEB_EMAIL = 'web-email'; case WEB_ADDRESS = 'web-address'; - case DEFAULT_LANGUAGE = 'default_language'; case TIMEZONE = 'timezone'; - case GOOGLE_TAG_MANAGER_ID = 'google-tag_manager_id'; case GOOGLE_WEBMASTER_ID = 'google-webmaster_id'; - public function label(): string - { - return __('domains/system/field.settings.'.str_replace('-', '.', $this->value)); - } - - public static function section(): array + /** + * Centralized Schema Definitions + */ + public function schema(): SettingSchema { - return [ - [ - __('domains/system/pages.settings.sections.web') => [ - self::WEB_NAME, - self::WEB_DESCRIPTION, - self::WEB_ADDRESS, - self::WEB_PHONE, - self::WEB_EMAIL, - self::WEB_LOGO, - self::WEB_FAVICON, - ], - ], - [ - __('domains/system/pages.settings.sections.general') => [ - self::DEFAULT_LANGUAGE, - self::TIMEZONE, - ], - __('domains/system/pages.settings.sections.webmaster') => [ - self::GOOGLE_TAG_MANAGER_ID, - self::GOOGLE_WEBMASTER_ID, - ], - ], + $imageRules = ['required', 'file', 'mimetypes:'.implode(',', FileType::IMAGE->mimeType()), 'max:1024']; + $imageAttrs = [ + 'allow-image-crop' => true, + 'allow-image-resize' => true, + 'allow-image-transform' => true, + 'image-crop-aspect-ratio' => '1:1', + 'image-resize-target-width' => '500', + 'image-resize-target-height' => '500', ]; - } - public function inputType(): InputType - { return match ($this) { - self::WEB_LOGO, self::WEB_FAVICON => InputType::FILE, - self::DEFAULT_LANGUAGE, self::TIMEZONE => InputType::SELECT, - self::WEB_DESCRIPTION => InputType::TEXTAREA, - default => InputType::TEXTLINE - }; - } + self::WEB_NAME => SettingSchema::make(InputType::TEXTLINE)->default('Acme Inc'), + self::WEB_DESCRIPTION => SettingSchema::make(InputType::TEXTAREA), + self::WEB_ADDRESS => SettingSchema::make(InputType::TEXTLINE)->default('123 Main St, Anytown, USA'), + self::WEB_PHONE => SettingSchema::make(InputType::TEXTLINE)->default('+1234567890'), + self::WEB_EMAIL => SettingSchema::make(InputType::TEXTLINE)->default('acme@web.io'), - public function inputAttributes(): array - { - $options = match ($this) { - self::WEB_LOGO, self::WEB_FAVICON => [ - 'allow-image-crop' => true, - 'allow-image-resize' => true, - 'allow-image-transform' => true, - 'image-crop-aspect-ratio' => '1:1', - 'image-resize-target-width' => '500', - 'image-resize-target-height' => '500', - ], - self::TIMEZONE, self::DEFAULT_LANGUAGE => ['options' => $this->options()], - default => [], - }; - $options['label'] = $this->label(); + self::WEB_LOGO, + self::WEB_FAVICON => SettingSchema::make(InputType::FILE, $imageRules)->attributes($imageAttrs), - return $options; - } + self::DEFAULT_LANGUAGE => SettingSchema::make(InputType::SELECT) + ->default('en') + ->options([ + 'en' => __('domains/system/enum.system_setting_key_options.default_language.en'), + 'id' => __('domains/system/enum.system_setting_key_options.default_language.id'), + ]), - public function validation(): array - { - return match ($this) { - self::WEB_LOGO, self::WEB_FAVICON => ['required', 'file', 'mimetypes:'.implode(',', FileType::IMAGE->mimeType()), 'max:1024'], - default => ['required', 'string'], + self::TIMEZONE => SettingSchema::make(InputType::SELECT) + ->default('UTC') + ->options([ + 'UTC' => __('domains/system/enum.system_setting_key_options.timezone.UTC'), + 'Asia/Jakarta' => __('domains/system/enum.system_setting_key_options.timezone.Asia/Jakarta'), + 'Asia/Makassar' => __('domains/system/enum.system_setting_key_options.timezone.Asia/Makassar'), + 'Asia/Jayapura' => __('domains/system/enum.system_setting_key_options.timezone.Asia/Jayapura'), + ]), + + default => SettingSchema::make(InputType::TEXTLINE)->rules(['nullable', 'string']), }; } - public function default(): ?string + public function default(): mixed { - return match ($this) { - self::DEFAULT_LANGUAGE => 'en', - self::TIMEZONE => 'UTC', - self::WEB_NAME => 'Acme Inc', - self::WEB_ADDRESS => '123 Main St, Anytown, USA', - self::WEB_PHONE => '+1234567890', - self::WEB_EMAIL => 'acme@web.io', - default => null - }; + return $this->schema()->default; } - public function options(): array + public function inputAttributes(): array { - return match ($this) { - self::DEFAULT_LANGUAGE => [ - 'en' => 'English', - 'id' => 'Indonesian', - ], - self::TIMEZONE => [ - 'UTC' => 'UTC', - 'Asia/Jakarta' => 'Asia/Jakarta', - 'Asia/Makassar' => 'Asia/Makassar', - 'Asia/Jayapura' => 'Asia/Jayapura', - ], - default => [], - }; + return array_merge($this->schema()->attributes, [ + 'label' => $this->label(), + 'options' => $this->schema()->type->isSelect() ? $this->schema()->options : '', + ]); } - public function isImage(): bool + public static function section(): array { - return in_array($this, [ - self::WEB_LOGO, - self::WEB_FAVICON, - ]); + return [ + [ + __('domains/system/pages.settings.sections.web') => [ + self::WEB_NAME, self::WEB_DESCRIPTION, self::WEB_ADDRESS, + self::WEB_PHONE, self::WEB_EMAIL, self::WEB_LOGO, self::WEB_FAVICON, + ], + ], + [ + __('domains/system/pages.settings.sections.general') => [self::DEFAULT_LANGUAGE, self::TIMEZONE], + __('domains/system/pages.settings.sections.webmaster') => [self::GOOGLE_TAG_MANAGER_ID, self::GOOGLE_WEBMASTER_ID], + ], + ]; } } diff --git a/app/Domains/System/Models/SystemSettings.php b/app/Domains/System/Models/SystemSettings.php index 7f43838..be9f5c3 100644 --- a/app/Domains/System/Models/SystemSettings.php +++ b/app/Domains/System/Models/SystemSettings.php @@ -2,27 +2,29 @@ namespace App\Domains\System\Models; -use App\Domains\System\Enums\SystemSettingKey; -use App\UI\Enums\InputType; use Exception; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\WithoutTimestamps; use Illuminate\Database\Eloquent\Model; -#[Fillable(['key', 'value'])] +#[Fillable(['key', 'value', 'type'])] #[WithoutTimestamps] class SystemSettings extends Model { + public static string $cacheName = 'system-settings'; + /** * @throws Exception */ public function getTranslatedValueAttribute(): ?string { - $key = SystemSettingKey::tryFrom($this->attributes['key']); - if ($key->inputType() == InputType::FILE && isset($this->attributes['value'])) { + $key = $this->attributes['type']::tryFrom($this->attributes['key']); + + $schema = $key->schema(); + if ($schema->type->isFile() && isset($this->attributes['value'])) { return asset_static($this->attributes['value']); - } elseif ($key->inputType() == InputType::SELECT) { - return $key->options()[$this->attributes['value']]; + } elseif ($schema->type->isSelect()) { + return $schema->options[$this->attributes['value']]; } return $this->attributes['value']; diff --git a/app/Domains/System/Providers/RelationshipServiceProvider.php b/app/Domains/System/Providers/RelationshipServiceProvider.php index 8b4ce40..7b923bb 100644 --- a/app/Domains/System/Providers/RelationshipServiceProvider.php +++ b/app/Domains/System/Providers/RelationshipServiceProvider.php @@ -13,7 +13,7 @@ class RelationshipServiceProvider extends ServiceProvider * relationship definitions. Use Model::resolveRelationUsing() here to wire * explicit polymorphic or foreign-key macros between models that live in * different domains — without introducing a hard compile-time dependency - * between those domains. + * between those domains/ * * Do NOT add route registrations, bindings, event listeners, or any other * bootstrapping logic here. Keep this file focused on relationships only. diff --git a/app/Domains/System/Providers/SystemServiceProvider.php b/app/Domains/System/Providers/SystemServiceProvider.php index 6dc3c8e..75d7d8f 100644 --- a/app/Domains/System/Providers/SystemServiceProvider.php +++ b/app/Domains/System/Providers/SystemServiceProvider.php @@ -32,6 +32,7 @@ class SystemServiceProvider extends ServiceProvider public function register(): void { $this->app->register(RelationshipServiceProvider::class); + $this->app->register(ViewServiceProvider::class); // Tell Laravel: "Whenever someone asks for GetSystemSettings, // give them the exact same object instance for the entire request." diff --git a/app/Domains/System/Queries/GetSystemSettings.php b/app/Domains/System/Queries/GetSystemSettings.php index c83e2e0..a26216e 100644 --- a/app/Domains/System/Queries/GetSystemSettings.php +++ b/app/Domains/System/Queries/GetSystemSettings.php @@ -21,8 +21,8 @@ class GetSystemSettings return $this->settings; } - $this->settings = Cache::rememberForever('system_settings', function () { - $settings = SystemSettings::pluck('value', 'key')->toArray(); + $this->settings = Cache::rememberForever(SystemSettings::$cacheName, function () { + $settings = SystemSettings::where('type', SystemSettingKey::class)->pluck('value', 'key')->toArray(); $finalSettings = []; foreach (SystemSettingKey::cases() as $key) { $finalSettings[$key->value] = $settings[$key->value] ?? $key->default(); diff --git a/app/Domains/System/Traits/Enum/HasPredicateMethod.php b/app/Domains/System/Traits/Enum/HasPredicateMethod.php index 1092b7d..b8a8f26 100644 --- a/app/Domains/System/Traits/Enum/HasPredicateMethod.php +++ b/app/Domains/System/Traits/Enum/HasPredicateMethod.php @@ -2,22 +2,29 @@ namespace App\Domains\System\Traits\Enum; +/* + * @mixin \BackedEnum + */ + +use BadMethodCallException; +use Illuminate\Support\Str; + trait HasPredicateMethod { public function __call(string $method, array $arguments): bool { if (str_starts_with($method, 'is')) { - $expectedCase = substr($method, 2); - $expectedCase = strtoupper($expectedCase); + $expectedCase = Str::substr($method, 2); + $expectedCase = Str::upper($expectedCase); foreach ($this::cases() as $case) { - if ($case->name === $expectedCase) { + if ($case->name === $expectedCase || $case->value === Str::kebab($expectedCase)) { return $this === $case; } } - throw new \BadMethodCallException("Method {$method} does not exist on ".self::class); + throw new BadMethodCallException("Method {$method} does not exist on ".self::class); } - return true; + throw new BadMethodCallException("Method {$method} does not exist on ".self::class); } } diff --git a/app/Domains/System/Traits/Model/HasSlugs.php b/app/Domains/System/Traits/Model/HasSlugs.php index 5fc4f03..eb872a2 100644 --- a/app/Domains/System/Traits/Model/HasSlugs.php +++ b/app/Domains/System/Traits/Model/HasSlugs.php @@ -13,6 +13,8 @@ trait HasSlugs public static function bootHasSlugs(): void { - static::saving(fn (self $model) => $model->slug = str($model->{$model->sluggable()})->slug()); + static::creating(function (Model $model) { + $model->slug = str($model->sluggable())->slug(); + }); } } diff --git a/app/Domains/System/Traits/Model/HasTranslation.php b/app/Domains/System/Traits/Model/HasTranslation.php new file mode 100644 index 0000000..78e2941 --- /dev/null +++ b/app/Domains/System/Traits/Model/HasTranslation.php @@ -0,0 +1,222 @@ + ['name' => 'Value', 'story' => '...'], 'ar' => [...]] + */ + protected array $translationsCache = []; + + /** + * Tracks whether translation records have been read from the database table for this instance. + */ + protected bool $translationsLoaded = false; + + /** + * Intercept the standard Eloquent model booting pipeline. + */ + public static function bootHasTranslation(): void + { + // Automatically save any dirty or staged translations when the parent model saves + static::saved(function (self $model) { + $model->saveTranslations(); + }); + + // Automatically drop related database rows when the parent record is deleted + static::deleted(function (self $model) { + $model->purgeTranslations(); + }); + } + + /** + * Magic Getter Interception: + * Intercepts access to properties defined in the $translatable array. + */ + public function __get($key) + { + if ($this->isTranslationAttribute($key)) { + return $this->translate($key, $this->getLocale()); + } + + return parent::__get($key); + } + + /** + * Magic Setter Interception: + * Intercepts updates to properties defined in the $translatable array. + */ + public function __set($key, $value) + { + if ($this->isTranslationAttribute($key)) { + $this->setTranslationValue($key, $this->getLocale(), $value); + + return; + } + + parent::__set($key, $value); + } + + /** + * Magic Isset Interception: + * Handles isset() evaluations for translatable fields. + */ + public function __isset($key) + { + if ($this->isTranslationAttribute($key)) { + return ! is_null($this->translate($key, $this->getLocale())); + } + + return parent::__isset($key); + } + + /** + * Override the standard Eloquent fill process to support nested language arrays + * Example: $model->fill(['en' => ['name' => 'Adam'], 'color_value' => 123]) + */ + public function fill(array $attributes) + { + foreach ($attributes as $key => $value) { + // Check if the key looks like a language code (e.g., 'en', 'ar', 'id') + if (is_array($value) && (strlen($key) === 2 || strlen($key) === 5)) { + foreach ($value as $translatedKey => $translatedValue) { + if ($this->isTranslationAttribute($translatedKey)) { + $this->setTranslationValue($translatedKey, $key, $translatedValue); + } + } + unset($attributes[$key]); + } + } + + return parent::fill($attributes); + } + + /** + * Public method to retrieve a field value for a specific language locale. + */ + public function translate(string $attribute, ?string $locale = null): ?string + { + // 1. High-Performance Left-Join Optimization: + // If the query used a leftJoin scope, the column exists directly on the primary attributes array. + if (array_key_exists($attribute, $this->attributes)) { + return $this->attributes[$attribute]; + } + + $locale = $locale ?? $this->getLocale(); + + // 2. Load translations from the database into the cache array if not already loaded + if (! $this->translationsLoaded && $this->exists) { + $this->loadTranslationsFromTable(); + } + + return $this->translationsCache[$locale][$attribute] ?? $this->getFallbackTranslation($attribute); + } + + /** + * Check if a specific string property name is declared as a translatable variable. + */ + public function isTranslationAttribute(string $key): bool + { + return isset($this->translatable) && in_array($key, $this->translatable); + } + + /** + * Load all rows from the target database translation table into local memory cache. + */ + public function loadTranslationsFromTable(): self + { + $records = DB::table($this->getTranslationTableName()) + ->where($this->getTranslationForeignKey(), $this->getKey()) + ->get(); + + foreach ($records as $record) { + foreach ((array) $record as $column => $value) { + if (in_array($column, ['id', $this->getTranslationForeignKey(), 'locale'])) { + continue; + } + $this->translationsCache[$record->locale][$column] = $value; + } + } + + $this->translationsLoaded = true; + + return $this; + } + + /** + * Staged Memory Update: Write property variables straight into the memory array. + */ + protected function setTranslationValue(string $attribute, string $locale, ?string $value): void + { + $this->translationsCache[$locale][$attribute] = $value; + } + + /** + * Database Mutation: Write cached memory arrays to the database table. + */ + protected function saveTranslations(): void + { + foreach ($this->translationsCache as $locale => $attributes) { + if (empty($attributes)) { + continue; + } + + DB::table($this->getTranslationTableName())->updateOrInsert( + [ + $this->getTranslationForeignKey() => $this->getKey(), + 'locale' => $locale, + ], + $attributes + ); + } + } + + /** + * Database Purge: Remove records from the database table. + */ + protected function purgeTranslations(): void + { + DB::table($this->getTranslationTableName()) + ->where($this->getTranslationForeignKey(), $this->getKey()) + ->delete(); + } + + /** + * Fallback Logic: Returns the first available translation if the requested language is missing. + */ + protected function getFallbackTranslation(string $attribute): ?string + { + foreach ($this->translationsCache as $locale => $attributes) { + if (! empty($attributes[$attribute])) { + return $attributes[$attribute]; + } + } + + return null; + } + + protected function getLocale(): string + { + return App::getLocale(); + } + + protected function getTranslationTableName(): string + { + return Str::singular($this->getTable()).'_translations'; + } + + protected function getTranslationForeignKey(): string + { + return Str::singular($this->getTable()).'_id'; + } +} diff --git a/app/Http/Controllers/Web/Academic/FacultyController.php b/app/Http/Controllers/Web/Academic/FacultyController.php index a1bafec..2c2d810 100644 --- a/app/Http/Controllers/Web/Academic/FacultyController.php +++ b/app/Http/Controllers/Web/Academic/FacultyController.php @@ -21,7 +21,7 @@ class FacultyController extends Controller #[LayoutData( header: 'domains/academic/seo.faculty.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/academic/seo.faculty.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Academic/StudyProgramController.php b/app/Http/Controllers/Web/Academic/StudyProgramController.php index 6ea40f4..4b286bd 100644 --- a/app/Http/Controllers/Web/Academic/StudyProgramController.php +++ b/app/Http/Controllers/Web/Academic/StudyProgramController.php @@ -14,15 +14,15 @@ class StudyProgramController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/academic/seo.study-program.title', - description: 'domains/academic/seo.study-program.description', - keywords: 'domains/academic/seo.study-program.keywords' + title: 'domains/academic/seo.study_program.title', + description: 'domains/academic/seo.study_program.description', + keywords: 'domains/academic/seo.study_program.keywords' )] #[LayoutData( - header: 'domains/academic/seo.study-program.title', + header: 'domains/academic/seo.study_program.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/academic/seo.study-program.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/academic/seo.study_program.title' => '', ], )] public function __invoke(StudyProgramDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Academic/TermController.php b/app/Http/Controllers/Web/Academic/TermController.php index 92c60fd..a03df17 100644 --- a/app/Http/Controllers/Web/Academic/TermController.php +++ b/app/Http/Controllers/Web/Academic/TermController.php @@ -21,7 +21,7 @@ class TermController extends Controller #[LayoutData( header: 'domains/academic/seo.term.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/academic/seo.term.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Account/ProfileController.php b/app/Http/Controllers/Web/Account/ProfileController.php index a90fcf0..b88a673 100644 --- a/app/Http/Controllers/Web/Account/ProfileController.php +++ b/app/Http/Controllers/Web/Account/ProfileController.php @@ -20,7 +20,7 @@ class ProfileController extends Controller #[LayoutData( header: 'domains/account/seo.profile.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/account/seo.profile.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Admission/AcademicProgramController.php b/app/Http/Controllers/Web/Admission/AcademicProgramController.php index 5b45117..3456159 100644 --- a/app/Http/Controllers/Web/Admission/AcademicProgramController.php +++ b/app/Http/Controllers/Web/Admission/AcademicProgramController.php @@ -14,15 +14,15 @@ class AcademicProgramController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/admission/seo.academic-program.title', - description: 'domains/admission/seo.academic-program.description', - keywords: 'domains/admission/seo.academic-program.keywords' + title: 'domains/admission/seo.academic_program.title', + description: 'domains/admission/seo.academic_program.description', + keywords: 'domains/admission/seo.academic_program.keywords' )] #[LayoutData( - header: 'domains/admission/seo.academic-program.title', + header: 'domains/admission/seo.academic_program.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/admission/seo.academic-program.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/admission/seo.academic_program.title' => '', ], )] public function __invoke(AcademicProgramDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Admission/AdmissionScheduleController.php b/app/Http/Controllers/Web/Admission/AdmissionScheduleController.php index bf10060..3039b60 100644 --- a/app/Http/Controllers/Web/Admission/AdmissionScheduleController.php +++ b/app/Http/Controllers/Web/Admission/AdmissionScheduleController.php @@ -14,15 +14,15 @@ class AdmissionScheduleController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/admission/seo.admission-schedule.title', - description: 'domains/admission/seo.admission-schedule.description', - keywords: 'domains/admission/seo.admission-schedule.keywords' + title: 'domains/admission/seo.admission_schedule.title', + description: 'domains/admission/seo.admission_schedule.description', + keywords: 'domains/admission/seo.admission_schedule.keywords' )] #[LayoutData( - header: 'domains/admission/seo.admission-schedule.title', + header: 'domains/admission/seo.admission_schedule.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/admission/seo.admission-schedule.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/admission/seo.admission_schedule.title' => '', ], )] public function __invoke(AdmissionScheduleDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Admission/AdmissionTrackController.php b/app/Http/Controllers/Web/Admission/AdmissionTrackController.php index ff3662b..753ba19 100644 --- a/app/Http/Controllers/Web/Admission/AdmissionTrackController.php +++ b/app/Http/Controllers/Web/Admission/AdmissionTrackController.php @@ -14,15 +14,15 @@ class AdmissionTrackController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/admission/seo.admission-track.title', - description: 'domains/admission/seo.admission-track.description', - keywords: 'domains/admission/seo.admission-track.keywords' + title: 'domains/admission/seo.admission_track.title', + description: 'domains/admission/seo.admission_track.description', + keywords: 'domains/admission/seo.admission_track.keywords' )] #[LayoutData( - header: 'domains/admission/seo.admission-track.title', + header: 'domains/admission/seo.admission_track.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/admission/seo.admission-track.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/admission/seo.admission_track.title' => '', ], )] public function __invoke(AdmissionTrackDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Admission/FeeTypeController.php b/app/Http/Controllers/Web/Admission/FeeTypeController.php index cad43b4..d61f1d9 100644 --- a/app/Http/Controllers/Web/Admission/FeeTypeController.php +++ b/app/Http/Controllers/Web/Admission/FeeTypeController.php @@ -14,15 +14,15 @@ class FeeTypeController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/admission/seo.fee-type.title', - description: 'domains/admission/seo.fee-type.description', - keywords: 'domains/admission/seo.fee-type.keywords' + title: 'domains/admission/seo.fee_type.title', + description: 'domains/admission/seo.fee_type.description', + keywords: 'domains/admission/seo.fee_type.keywords' )] #[LayoutData( - header: 'domains/admission/seo.fee-type.title', + header: 'domains/admission/seo.fee_type.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/admission/seo.fee-type.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/admission/seo.fee_type.title' => '', ], )] public function __invoke(FeeTypeDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Channel/ClientController.php b/app/Http/Controllers/Web/Channel/ClientController.php index 20e30d0..fdb1c93 100644 --- a/app/Http/Controllers/Web/Channel/ClientController.php +++ b/app/Http/Controllers/Web/Channel/ClientController.php @@ -21,7 +21,7 @@ class ClientController extends Controller #[LayoutData( header: 'domains/channel/seo.client.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/channel/seo.client.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Finance/ChartOfAccountController.php b/app/Http/Controllers/Web/Finance/ChartOfAccountController.php index e2044b4..1932c90 100644 --- a/app/Http/Controllers/Web/Finance/ChartOfAccountController.php +++ b/app/Http/Controllers/Web/Finance/ChartOfAccountController.php @@ -21,7 +21,7 @@ class ChartOfAccountController extends Controller #[LayoutData( header: 'domains/finance/seo.coa.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/finance/seo.coa.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Finance/InvoiceController.php b/app/Http/Controllers/Web/Finance/InvoiceController.php index f98e262..cf1a621 100644 --- a/app/Http/Controllers/Web/Finance/InvoiceController.php +++ b/app/Http/Controllers/Web/Finance/InvoiceController.php @@ -21,7 +21,7 @@ class InvoiceController extends Controller #[LayoutData( header: 'domains/finance/seo.invoice.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/finance/seo.invoice.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Finance/ProductMappingController.php b/app/Http/Controllers/Web/Finance/ProductMappingController.php index 0e4b4b6..f5797b2 100644 --- a/app/Http/Controllers/Web/Finance/ProductMappingController.php +++ b/app/Http/Controllers/Web/Finance/ProductMappingController.php @@ -14,15 +14,15 @@ class ProductMappingController extends Controller * Handle the incoming request. */ #[Seo( - title: 'domains/finance/seo.product-mapping.title', - description: 'domains/finance/seo.product-mapping.description', - keywords: 'domains/finance/seo.product-mapping.keywords' + title: 'domains/finance/seo.product_mapping.title', + description: 'domains/finance/seo.product_mapping.description', + keywords: 'domains/finance/seo.product_mapping.keywords' )] #[LayoutData( - header: 'domains/finance/seo.product-mapping.title', + header: 'domains/finance/seo.product_mapping.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', - 'domains/finance/seo.product-mapping.title' => '', + 'ui/menu.dashboard' => 'dashboard', + 'domains/finance/seo.product_mapping.title' => '', ], )] public function __invoke(ProductMappingDataTable $dataTable) diff --git a/app/Http/Controllers/Web/Identity/RoleController.php b/app/Http/Controllers/Web/Identity/RoleController.php index 2e86346..554ce78 100644 --- a/app/Http/Controllers/Web/Identity/RoleController.php +++ b/app/Http/Controllers/Web/Identity/RoleController.php @@ -15,7 +15,7 @@ class RoleController extends Controller #[LayoutData( header: 'domains/identity/seo.role.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/identity/seo.role.title' => '', ], )] diff --git a/app/Http/Controllers/Web/Identity/UserController.php b/app/Http/Controllers/Web/Identity/UserController.php index 5a88eac..8ee87f1 100644 --- a/app/Http/Controllers/Web/Identity/UserController.php +++ b/app/Http/Controllers/Web/Identity/UserController.php @@ -15,7 +15,7 @@ class UserController extends Controller #[LayoutData( header: 'domains/identity/seo.user.title', breadcrumbs: [ - 'ui.menu.dashboard' => 'dashboard', + 'ui/menu.dashboard' => 'dashboard', 'domains/identity/seo.user.title' => '', ], )] diff --git a/app/Http/DataTables/Academic/FacultyDataTable.php b/app/Http/DataTables/Academic/FacultyDataTable.php index d65fb5e..e352f0c 100644 --- a/app/Http/DataTables/Academic/FacultyDataTable.php +++ b/app/Http/DataTables/Academic/FacultyDataTable.php @@ -30,9 +30,9 @@ class FacultyDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.admission-schedule')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.admission-schedule')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.faculty')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.faculty')]), 'permission' => auth()->user()->can('delete', $faculty), ], 'table_name' => 'faculty-table', @@ -80,7 +80,7 @@ class FacultyDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -115,7 +115,7 @@ class FacultyDataTable extends DataTable ->width(10) ->title(__('domains/academic/field.faculty.code')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Academic/StudyProgramDataTable.php b/app/Http/DataTables/Academic/StudyProgramDataTable.php index 2417af5..9e0fc86 100644 --- a/app/Http/DataTables/Academic/StudyProgramDataTable.php +++ b/app/Http/DataTables/Academic/StudyProgramDataTable.php @@ -34,9 +34,9 @@ class StudyProgramDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.admission-schedule')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.admission-schedule')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.study_program')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.study_program')]), 'permission' => auth()->user()->can('delete', $studyProgram), ], 'table_name' => 'studyprogram-table', @@ -86,7 +86,7 @@ class StudyProgramDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -116,17 +116,17 @@ class StudyProgramDataTable extends DataTable ->width(10) ->title('#'), Column::make('name') - ->title(__('domains/academic/field.study-program.name')), + ->title(__('domains/academic/field.study_program.name')), Column::computed('code') ->width(50) - ->title(__('domains/academic/field.study-program.code')), + ->title(__('domains/academic/field.study_program.code')), Column::make('faculty_name') ->title(__('domains/academic/field.faculty.name')), Column::computed('status') ->width(50) - ->title(__('domains/academic/field.study-program.status')), + ->title(__('domains/academic/field.study_program.status')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Academic/TermDataTable.php b/app/Http/DataTables/Academic/TermDataTable.php index 157fef7..e44c02d 100644 --- a/app/Http/DataTables/Academic/TermDataTable.php +++ b/app/Http/DataTables/Academic/TermDataTable.php @@ -30,9 +30,9 @@ class TermDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.admission-schedule')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.admission-schedule')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.term')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.term')]), 'permission' => auth()->user()->can('delete', $term), ], 'table_name' => 'term-table', @@ -80,7 +80,7 @@ class TermDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -127,7 +127,7 @@ class TermDataTable extends DataTable ->width(150) ->title(__('domains/academic/field.term.date_end')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Admission/AcademicProgramDataTable.php b/app/Http/DataTables/Admission/AcademicProgramDataTable.php index e460789..9d74296 100644 --- a/app/Http/DataTables/Admission/AcademicProgramDataTable.php +++ b/app/Http/DataTables/Admission/AcademicProgramDataTable.php @@ -34,9 +34,9 @@ class AcademicProgramDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.academic_program')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.academic_program')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.academic_program')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.academic_program')]), 'permission' => auth()->user()->can('delete', $academicProgram), ], 'table_name' => 'academicprogram-table', @@ -84,7 +84,7 @@ class AcademicProgramDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -114,14 +114,14 @@ class AcademicProgramDataTable extends DataTable ->width(10) ->title('#'), Column::make('code') - ->title(__('domains/admission/field.academic-program.code')), + ->title(__('domains/admission/field.academic_program.code')), Column::make('name') - ->title(__('domains/admission/field.academic-program.name')), + ->title(__('domains/admission/field.academic_program.name')), Column::make('status') ->width(100) - ->title(__('domains/admission/field.academic-program.status')), + ->title(__('domains/admission/field.academic_program.status')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Admission/AdmissionScheduleDataTable.php b/app/Http/DataTables/Admission/AdmissionScheduleDataTable.php index 85c1b41..c7cd4d7 100644 --- a/app/Http/DataTables/Admission/AdmissionScheduleDataTable.php +++ b/app/Http/DataTables/Admission/AdmissionScheduleDataTable.php @@ -34,9 +34,9 @@ class AdmissionScheduleDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.admission-schedule')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.admission-schedule')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.admission_schedule')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.admission_schedule')]), 'permission' => auth()->user()->can('delete', $admissionSchedule), ], 'table_name' => 'admissionschedule-table', @@ -87,7 +87,7 @@ class AdmissionScheduleDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -118,18 +118,18 @@ class AdmissionScheduleDataTable extends DataTable ->title('#'), Column::make('admission_track_name') ->width(450) - ->title(__('domains/admission/field.admission-schedule.track_name')), + ->title(__('domains/admission/field.admission_schedule.track_name')), Column::make('term_name') ->width(250) - ->title(__('domains/admission/field.admission-schedule.term_name')), + ->title(__('domains/admission/field.admission_schedule.term_name')), Column::computed('date_start') ->width(150) - ->title(__('domains/admission/field.admission-schedule.date-start')), + ->title(__('domains/admission/field.admission_schedule.date_start')), Column::computed('date_end') ->width(150) - ->title(__('domains/admission/field.admission-schedule.date-end')), + ->title(__('domains/admission/field.admission_schedule.date_end')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->addClass('text-center'), diff --git a/app/Http/DataTables/Admission/AdmissionTrackDataTable.php b/app/Http/DataTables/Admission/AdmissionTrackDataTable.php index 7aa1ffd..083e62e 100644 --- a/app/Http/DataTables/Admission/AdmissionTrackDataTable.php +++ b/app/Http/DataTables/Admission/AdmissionTrackDataTable.php @@ -34,9 +34,9 @@ class AdmissionTrackDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.admission-track')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.admission-track')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.admission_track')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.admission_track')]), 'permission' => auth()->user()->can('delete', $admissionTrack), ], 'table_name' => 'admissiontrack-table', @@ -84,7 +84,7 @@ class AdmissionTrackDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -114,12 +114,12 @@ class AdmissionTrackDataTable extends DataTable ->width(10) ->title('#'), Column::make('name') - ->title(__('domains/admission/field.admission-track.name')), + ->title(__('domains/admission/field.admission_track.name')), Column::computed('status') ->width(50) - ->title(__('domains/admission/field.admission-track.status')), + ->title(__('domains/admission/field.admission_track.status')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(30) diff --git a/app/Http/DataTables/Admission/FeeTypeDataTable.php b/app/Http/DataTables/Admission/FeeTypeDataTable.php index 89d2665..708e4b7 100644 --- a/app/Http/DataTables/Admission/FeeTypeDataTable.php +++ b/app/Http/DataTables/Admission/FeeTypeDataTable.php @@ -27,9 +27,9 @@ class FeeTypeDataTable extends DataTable 'log' => true, 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.fee-type')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.fee-type')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.fee_type')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.fee_type')]), 'permission' => auth()->user()->can('delete', $feeType), ], 'table_name' => 'feetype-table', @@ -77,7 +77,7 @@ class FeeTypeDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -107,11 +107,11 @@ class FeeTypeDataTable extends DataTable ->width(10) ->title('#'), Column::make('name') - ->title(__('domains/admission/field.fee-type.name')), + ->title(__('domains/admission/field.fee_type.name')), Column::make('billing_cycle') - ->title(__('domains/admission/field.fee-type.billing_cycle')), + ->title(__('domains/admission/field.fee_type.billing_cycle')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Channel/ClientDataTable.php b/app/Http/DataTables/Channel/ClientDataTable.php index 2e540df..2feb591 100644 --- a/app/Http/DataTables/Channel/ClientDataTable.php +++ b/app/Http/DataTables/Channel/ClientDataTable.php @@ -20,9 +20,10 @@ class ClientDataTable extends DataTable public function dataTable(QueryBuilder $query): EloquentDataTable { return (new EloquentDataTable($query)) + ->editColumn('auth_type', fn (Client $client) => $client->auth_type->label()) ->addColumn( 'action', - fn ($client) => view('components.datatables.action-button', [ + fn (Client $client) => view('components.datatables.action-button', [ 'log' => true, 'edit' => [ 'modal' => 'client-form-modal', @@ -30,9 +31,9 @@ class ClientDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.client')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.client')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.client')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.client')]), 'permission' => auth()->user()->can('delete', $client), ], 'table_name' => 'client-table', @@ -80,7 +81,7 @@ class ClientDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -94,6 +95,10 @@ class ClientDataTable extends DataTable ->action('$("#client-form-modal").modal("show");') ->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) ->addClass('btn-sm'), + Button::make() + ->text(svg('tabler-api', ['width' => 16, 'height' => 16])->toHtml()) + ->action('$("#api-form-modal").modal("show");') + ->addClass('btn-sm btn-info'), Button::make('reload') ->text(svg('tabler-reload', ['width' => 16, 'height' => 16])->toHtml()) ->addClass('btn-sm'), @@ -111,12 +116,14 @@ class ClientDataTable extends DataTable ->title('#'), Column::make('name') ->title(__('domains/channel/field.client.name')), - Column::make('code') - ->title(__('domains/channel/field.client.code')), - Column::make('url') - ->title(__('domains/channel/field.client.url')), + Column::make('domain') + ->title(__('domains/channel/field.client.domain')), + Column::make('webhook') + ->title(__('domains/channel/field.client.webhook')), + Column::make('auth_type') + ->title(__('domains/channel/field.client.auth_type')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Finance/ChartOfAccountDataTable.php b/app/Http/DataTables/Finance/ChartOfAccountDataTable.php index 33cb946..15e1c8b 100644 --- a/app/Http/DataTables/Finance/ChartOfAccountDataTable.php +++ b/app/Http/DataTables/Finance/ChartOfAccountDataTable.php @@ -25,14 +25,14 @@ class ChartOfAccountDataTable extends DataTable fn ($coa) => view('components.datatables.action-button', [ 'log' => true, 'edit' => [ - 'modal' => 'coa-form-modal', + 'modal' => 'chartofaccount-form-modal', 'permission' => auth()->user()->can('update', $coa), ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.chart-of-account')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.chart-of-account')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.chart_of_account')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.chart_of_account')]), 'permission' => auth()->user()->can('delete', $coa), ], 'table_name' => 'chartofaccount-table', @@ -80,7 +80,7 @@ class ChartOfAccountDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -91,7 +91,7 @@ class ChartOfAccountDataTable extends DataTable ]) ->buttons([ Button::make('add') - ->action('$("#coa-form-modal").modal("show");') + ->action('$("#chartofaccount-form-modal").modal("show");') ->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) ->addClass('btn-sm'), Button::make('reload') @@ -119,7 +119,7 @@ class ChartOfAccountDataTable extends DataTable ->width(100) ->title(__('domains/finance/field.coa.status')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Finance/InvoiceDataTable.php b/app/Http/DataTables/Finance/InvoiceDataTable.php index c8395bd..a4fa821 100644 --- a/app/Http/DataTables/Finance/InvoiceDataTable.php +++ b/app/Http/DataTables/Finance/InvoiceDataTable.php @@ -61,7 +61,7 @@ class InvoiceDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, diff --git a/app/Http/DataTables/Finance/ProductMappingDataTable.php b/app/Http/DataTables/Finance/ProductMappingDataTable.php index 79e5631..2f10e96 100644 --- a/app/Http/DataTables/Finance/ProductMappingDataTable.php +++ b/app/Http/DataTables/Finance/ProductMappingDataTable.php @@ -30,9 +30,9 @@ class ProductMappingDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.product-mapping')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.product-mapping')]), + 'title' => __('ui/button.delete'), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.product_mapping')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.product_mapping')]), 'permission' => auth()->user()->can('delete', $productMapping), ], 'table_name' => 'productmapping-table', @@ -80,7 +80,7 @@ class ProductMappingDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -118,7 +118,7 @@ class ProductMappingDataTable extends DataTable Column::make('client.name') ->title(__('domains/finance/field.product_mapping.client_name')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Identity/RoleDataTable.php b/app/Http/DataTables/Identity/RoleDataTable.php index 0127f05..e9c4d97 100644 --- a/app/Http/DataTables/Identity/RoleDataTable.php +++ b/app/Http/DataTables/Identity/RoleDataTable.php @@ -37,12 +37,12 @@ class RoleDataTable extends DataTable ], 'delete' => [ 'url' => null, - 'title' => __('ui.button.delete'), + 'title' => __('ui/button.delete'), 'permission' => $role->name == RoleType::SYSTEM_ADMIN->value ? false : auth()->user()->can('delete', $role), - 'message' => __('ui.confirmation.delete', ['resource' => __('resources.role')]), - 'success_message' => __('ui.crud.success.deleted', ['resource' => __('resources.role')]), + 'message' => __('ui/confirmation.delete', ['resource' => __('resources.role')]), + 'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.role')]), ], 'table_name' => 'role-table', 'id' => $role->ulid, @@ -87,7 +87,7 @@ class RoleDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], ]) ->buttons([ @@ -118,7 +118,7 @@ class RoleDataTable extends DataTable Column::computed('guard_name') ->title(__('domains/identity/field.role.guard_name')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/DataTables/Identity/UserDataTable.php b/app/Http/DataTables/Identity/UserDataTable.php index bfb1b20..0991fde 100644 --- a/app/Http/DataTables/Identity/UserDataTable.php +++ b/app/Http/DataTables/Identity/UserDataTable.php @@ -46,14 +46,14 @@ class UserDataTable extends DataTable 'delete' => [ 'url' => null, 'title' => $user->status->isActive() - ? __('ui.button.suspend') - : __('ui.button.delete'), + ? __('ui/button.suspend') + : __('ui/button.delete'), 'message' => $user->status->isActive() - ? __('ui.confirmation.suspend', ['resource' => __('resources.user')]) - : __('ui.confirmation.delete', ['resource' => __('resources.user')]), + ? __('ui/confirmation.suspend', ['resource' => __('resources.user')]) + : __('ui/confirmation.delete', ['resource' => __('resources.user')]), 'success_message' => $user->status->isActive() - ? __('ui.crud.success.suspended', ['resource' => __('resources.user')]) - : __('ui.crud.success.deleted', ['resource' => __('resources.user')]), + ? __('ui/crud.success.suspended', ['resource' => __('resources.user')]) + : __('ui/crud.success.deleted', ['resource' => __('resources.user')]), 'permission' => auth()->user()->can('delete', $user), ], 'table_name' => 'user-table', @@ -135,7 +135,7 @@ class UserDataTable extends DataTable ->parameters([ 'language' => [ 'search' => '', - 'searchPlaceholder' => __('ui.button.lookup'), + 'searchPlaceholder' => __('ui/button.lookup'), ], 'fixedColumns' => [ 'start' => 2, @@ -155,7 +155,7 @@ class UserDataTable extends DataTable ->action("Livewire.dispatch('export-excel')"), Button::make('excel') ->text(svg('tabler-table-import', ['width' => 16, 'height' => 16])->toHtml()) - ->titleAttr(__('ui.title.import', ['resource' => 'Excel'])) + ->titleAttr(__('ui/title.import', ['resource' => 'Excel'])) ->addClass('btn-sm') ->action("$('#excel-import-modal').modal('show')"), Button::make('reload') @@ -183,7 +183,7 @@ class UserDataTable extends DataTable Column::computed('status') ->title(__('domains/identity/field.user.status')), Column::computed('action') - ->title(__('ui.label.actions')) + ->title(__('ui/label.actions')) ->exportable(false) ->printable(false) ->width(60) diff --git a/app/Http/Requests/Api/ApiRequest.php b/app/Http/Requests/Api/ApiRequest.php index a94eb24..a825bbb 100644 --- a/app/Http/Requests/Api/ApiRequest.php +++ b/app/Http/Requests/Api/ApiRequest.php @@ -18,7 +18,7 @@ abstract class ApiRequest extends FormRequest protected function failedValidation(Validator $validator) { throw new HttpResponseException(response()->json([ - 'message' => trans('ui.crud.error.validation_failed'), + 'message' => trans('ui/crud.error.validation_failed'), 'errors' => $validator->errors(), ], 422)); } diff --git a/app/Livewire/Concerns/WithModal.php b/app/Livewire/Concerns/WithModal.php index 7fa598e..3f6fb9a 100644 --- a/app/Livewire/Concerns/WithModal.php +++ b/app/Livewire/Concerns/WithModal.php @@ -25,7 +25,7 @@ trait WithModal { $resource = __('resources.'.$this->resourceName); - return __('ui.title.'.$this->mode, ['resource' => $resource]); + return __('ui/title.'.$this->mode, ['resource' => $resource]); } #[Computed] @@ -34,9 +34,9 @@ trait WithModal $resource = __('resources.'.$this->resourceName); return match ($this->mode) { - 'create' => __('ui.crud.success.created', ['resource' => $resource]), - 'update' => __('ui.crud.success.updated', ['resource' => $resource]), - default => __('ui.crud.success.deleted', ['resource' => $resource]), + 'create' => __('ui/crud.success.created', ['resource' => $resource]), + 'update' => __('ui/crud.success.updated', ['resource' => $resource]), + default => __('ui/crud.success.deleted', ['resource' => $resource]), }; } } diff --git a/app/Livewire/Forms/Academic/FacultyForm.php b/app/Livewire/Forms/Academic/FacultyForm.php index c671043..27ec7c5 100644 --- a/app/Livewire/Forms/Academic/FacultyForm.php +++ b/app/Livewire/Forms/Academic/FacultyForm.php @@ -2,6 +2,7 @@ namespace App\Livewire\Forms\Academic; +use App\Domains\System\Enums\LifecycleStatus; use Livewire\Attributes\Validate; use Livewire\Form; @@ -13,6 +14,9 @@ class FacultyForm extends Form #[Validate('required|string|max:255', as: 'domains/academic/field.faculty.code')] public string $code = ''; + #[Validate('required')] + public LifecycleStatus $status = LifecycleStatus::ACTIVE; + #[Validate('nullable|string|max:255', as: 'domains/academic/field.faculty.external_id')] public ?string $external_id = null; } diff --git a/app/Livewire/Forms/Channel/ClientForm.php b/app/Livewire/Forms/Channel/ClientForm.php index f593586..e8adde5 100644 --- a/app/Livewire/Forms/Channel/ClientForm.php +++ b/app/Livewire/Forms/Channel/ClientForm.php @@ -2,6 +2,7 @@ namespace App\Livewire\Forms\Channel; +use App\Domains\Channel\Enums\Client\AuthType; use Livewire\Attributes\Validate; use Livewire\Form; @@ -10,9 +11,43 @@ class ClientForm extends Form #[Validate('required|string|max:255', as: 'domains/channel/field.client.name')] public string $name = ''; - #[Validate('required|string|max:255', as: 'domains/channel/field.client.code')] - public string $code = ''; + #[Validate('required|max:255', as: 'domains/channel/field.client.domain')] + public string $domain = ''; - #[Validate('required|url|max:255', as: 'domains/channel/field.client.url')] - public string $url = ''; + #[Validate('required', as: 'domains/channel/field.client.auth_type')] + public AuthType $auth_type = AuthType::NONE; + + #[Validate(as: [ + 'credentials' => 'domains/channel/field.client.credentials', + 'credentials.username' => 'domains/channel/field.client.credentials.username', + 'credentials.password' => 'domains/channel/field.client.credentials.password', + 'credentials.token' => 'domains/channel/field.client.credentials.token', + ])] + public array $credentials = []; + + #[Validate('required|max:255', as: 'domains/channel/field.client.webhook')] + public string $webhook = ''; + + public function updatingAuthType(): void + { + $this->reset('credentials'); + } + + public function rules(): array + { + if ($this->auth_type === AuthType::TOKEN) { + return [ + 'credentials.token' => 'required', + ]; + } + + if ($this->auth_type == AuthType::BASIC) { + return [ + 'credentials.username' => 'required', + 'credentials.password' => 'required', + ]; + } + + return []; + } } diff --git a/app/UI/Actions/ApplyLayoutMetadata.php b/app/UI/Actions/ApplyLayoutMetadata.php index 7586dc9..89405e0 100644 --- a/app/UI/Actions/ApplyLayoutMetadata.php +++ b/app/UI/Actions/ApplyLayoutMetadata.php @@ -15,18 +15,11 @@ class ApplyLayoutMetadata public function execute(LayoutData $attributeInstance, array|object $dataContext): void { $contextTarget = $attributeInstance->context; - - // Use data_get to extract nested context if dot-notation is used (e.g., 'project.owner') - // Falls back to the entire data context if the target path isn't found or is null. - $resolvedContext = ! empty($contextTarget) - ? data_get($dataContext, $contextTarget, $dataContext) - : $dataContext; - $breadcrumbs = []; foreach ($attributeInstance->breadcrumbs as $labelKey => $routeConfig) { - // 1. Resolve the text label using our resolved nested context - $label = $this->textResolver->execute($labelKey, $resolvedContext, $contextTarget); + // 1. Resolve the text label (Supports translation keys or direct placeholders) + $label = $this->textResolver->execute($labelKey, $dataContext, $contextTarget); $url = null; if (! empty($routeConfig)) { @@ -39,8 +32,8 @@ class ApplyLayoutMetadata $rawParams = $routeConfig[1] ?? []; foreach ($rawParams as $paramKey => $paramValue) { - // Pass the nested context down to your string resolver - $resolvedValue = $this->textResolver->execute($paramValue, $resolvedContext, $contextTarget); + // Resolve internal variable bindings within parameters (e.g., "{user.id}" -> 4) + $resolvedValue = $this->textResolver->execute($paramValue, $dataContext, $contextTarget); $routeParams[$paramKey] = $resolvedValue; } } @@ -64,10 +57,10 @@ class ApplyLayoutMetadata ]; } - // 3. Resolve layout headline text patterns using our nested context + // 3. Resolve layout headline text patterns $header = null; if ($attributeInstance->header) { - $header = $this->textResolver->execute($attributeInstance->header, $resolvedContext, $contextTarget); + $header = $this->textResolver->execute($attributeInstance->header, $dataContext, $contextTarget); } if (empty($header) && ! empty($breadcrumbs)) { diff --git a/app/UI/Actions/ResolveDynamicText.php b/app/UI/Actions/ResolveDynamicText.php old mode 100644 new mode 100755 index 982f225..9e23008 --- a/app/UI/Actions/ResolveDynamicText.php +++ b/app/UI/Actions/ResolveDynamicText.php @@ -43,7 +43,7 @@ class ResolveDynamicText private function resolveExplicitPlaceholders(string $text, array|object $data, ?string $contextTarget): string { - preg_match_all('/\{([^}]+)\}/', $text, $matches); + preg_match_all('/\{([^}]+)}/', $text, $matches); if (empty($matches[1])) { return $text; } diff --git a/app/UI/Enums/Concerns/InteractsWithLabels.php b/app/UI/Enums/Concerns/InteractsWithLabels.php index e7bcbf9..789135f 100644 --- a/app/UI/Enums/Concerns/InteractsWithLabels.php +++ b/app/UI/Enums/Concerns/InteractsWithLabels.php @@ -19,13 +19,24 @@ trait InteractsWithLabels { $fqcn = static::class; - $domain = Str::between($fqcn, 'App\\Domains\\', '\\Enums\\'); - $domainSlug = Str::kebab($domain); - - $className = Str::afterLast($fqcn, '\\'); - $enumSlug = Str::kebab($className); - - $translationKey = "domains/{$domainSlug}/enum.{$enumSlug}.{$this->value}"; + if (Str::startsWith($fqcn, 'App\\Domains\\')) { + $domain = Str::between($fqcn, 'App\\Domains\\', '\\Enums\\'); + $domainSlug = Str::kebab($domain); + + $className = Str::afterLast($fqcn, '\\'); + $enumSlug = Str::snake($className); + + $translationKey = "domains/{$domainSlug}/enum.{$enumSlug}.{$this->value}"; + } elseif (Str::startsWith($fqcn, 'App\\UI\\Enums\\')) { + $className = Str::afterLast($fqcn, '\\'); + $enumSlug = Str::snake($className); + + $translationKey = "ui/enum.{$enumSlug}.{$this->value}"; + } else { + $className = Str::afterLast($fqcn, '\\'); + $enumSlug = Str::snake($className); + $translationKey = "enum.{$enumSlug}.{$this->value}"; + } return __($translationKey); } diff --git a/app/UI/Enums/Contracts/HasSchema.php b/app/UI/Enums/Contracts/HasSchema.php new file mode 100644 index 0000000..fd22d37 --- /dev/null +++ b/app/UI/Enums/Contracts/HasSchema.php @@ -0,0 +1,10 @@ +type, $this->rules, $default, $this->options, $this->attributes); + } + + public function rules(array $rules): self + { + return new self($this->type, $rules, $this->default, $this->options, $this->attributes); + } + + public function options(array $options): self + { + // If the array is simple (non-associative), we should try to localize the values if they are Enums + // But for now, we just pass it as is, or expect the caller to handle it. + // The common case is ['value' => 'Label'] + return new self($this->type, $this->rules, $this->default, $options, $this->attributes); + } + + public function attributes(array $attributes): self + { + return new self($this->type, $this->rules, $this->default, $this->options, $attributes); + } +} diff --git a/composer.lock b/composer.lock index 0e6395e..a92f65f 100644 --- a/composer.lock +++ b/composer.lock @@ -133,16 +133,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.384.4", + "version": "3.390.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "8e232a5703896541a7a34691a41ece5bd6170269" + "reference": "c75d5f489113e3c140d5a37602375e4359b66a75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8e232a5703896541a7a34691a41ece5bd6170269", - "reference": "8e232a5703896541a7a34691a41ece5bd6170269", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c75d5f489113e3c140d5a37602375e4359b66a75", + "reference": "c75d5f489113e3c140d5a37602375e4359b66a75", "shasum": "" }, "require": { @@ -150,10 +150,10 @@ "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/promises": "^2.0", - "guzzlehttp/psr7": "^2.4.5", - "mtdowling/jmespath.php": "^2.8.0", + "guzzlehttp/guzzle": "^7.8.2 || ^8.0", + "guzzlehttp/promises": "^2.0.3 || ^3.0", + "guzzlehttp/psr7": "^2.6.3 || ^3.0", + "mtdowling/jmespath.php": "^2.9.1", "php": ">=8.1", "psr/http-message": "^1.0 || ^2.0", "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" @@ -224,9 +224,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.384.4" + "source": "https://github.com/aws/aws-sdk-php/tree/3.390.1" }, - "time": "2026-06-05T18:05:57+00:00" + "time": "2026-07-31T02:53:14+00:00" }, { "name": "barryvdh/laravel-dompdf", @@ -307,16 +307,16 @@ }, { "name": "blade-ui-kit/blade-icons", - "version": "1.10.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/driesvints/blade-icons.git", - "reference": "74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a" + "reference": "6e072d021ea6249986c330b93293c33d0c4f0e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a", - "reference": "74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a", + "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/6e072d021ea6249986c330b93293c33d0c4f0e34", + "reference": "6e072d021ea6249986c330b93293c33d0c4f0e34", "shasum": "" }, "require": { @@ -384,27 +384,26 @@ "type": "paypal" } ], - "time": "2026-04-23T19:03:45+00:00" + "time": "2026-06-30T09:44:12+00:00" }, { "name": "brick/math", - "version": "0.14.8", + "version": "0.18.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", - "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", + "url": "https://api.github.com/repos/brick/math/zipball/82944324d1c1bdb2c2618e89978d4e2ad78d69ad", + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad", "shasum": "" }, "require": { "php": "^8.2" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.2", "phpstan/phpstan": "2.1.22", "phpunit/phpunit": "^11.5" }, @@ -436,7 +435,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.8" + "source": "https://github.com/brick/math/tree/0.18.0" }, "funding": [ { @@ -444,7 +443,7 @@ "type": "github" } ], - "time": "2026-02-10T14:33:43+00:00" + "time": "2026-06-14T18:21:03+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -517,28 +516,29 @@ }, { "name": "composer/pcre", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, "conflict": { - "phpstan/phpstan": "<1.11.10" + "phpstan/phpstan": "<2.2.2" }, "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9" }, "type": "library", "extra": { @@ -576,7 +576,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" + "source": "https://github.com/composer/pcre/tree/3.4.0" }, "funding": [ { @@ -586,13 +586,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-11-12T16:29:46+00:00" + "time": "2026-06-07T11:47:49+00:00" }, { "name": "composer/semver", @@ -915,16 +911,16 @@ }, { "name": "dompdf/dompdf", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496" + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", - "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/6d4b4eb8500f7a786da8868ba463a71b725a4005", + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005", "shasum": "" }, "require": { @@ -973,9 +969,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.5" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.6" }, - "time": "2026-03-03T13:54:37+00:00" + "time": "2026-07-20T12:29:38+00:00" }, { "name": "dompdf/php-font-lib", @@ -1384,26 +1380,26 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.11.1", + "version": "7.15.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "5af96f374e0ab4ebd747b8310888c99d3adb0a8c" + "reference": "744101956d78b7c1384d0cbf379db13e859167bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/5af96f374e0ab4ebd747b8310888c99d3adb0a8c", - "reference": "5af96f374e0ab4ebd747b8310888c99d3adb0a8c", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/744101956d78b7c1384d0cbf379db13e859167bf", + "reference": "744101956d78b7c1384d0cbf379db13e859167bf", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.5", - "guzzlehttp/psr7": "^2.11", + "guzzlehttp/promises": "^2.5.1", + "guzzlehttp/psr7": "^2.13", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" @@ -1411,8 +1407,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "guzzle/client-integration-tests": "3.0.2", - "guzzlehttp/test-server": "^0.5", + "guzzle/client-integration-tests": "3.0.3", + "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" @@ -1492,7 +1488,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.11.1" + "source": "https://github.com/guzzle/guzzle/tree/7.15.2" }, "funding": [ { @@ -1508,20 +1504,20 @@ "type": "tidelift" } ], - "time": "2026-06-07T22:54:06+00:00" + "time": "2026-07-26T23:23:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.5.0", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "4360e982f87f5f258bf872d094647791db2f4c8e" + "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/4360e982f87f5f258bf872d094647791db2f4c8e", - "reference": "4360e982f87f5f258bf872d094647791db2f4c8e", + "url": "https://api.github.com/repos/guzzle/promises/zipball/9ad1e4fc607446a055b95870c7f668e93b5cff29", + "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29", "shasum": "" }, "require": { @@ -1576,7 +1572,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.5.0" + "source": "https://github.com/guzzle/promises/tree/2.5.1" }, "funding": [ { @@ -1592,20 +1588,20 @@ "type": "tidelift" } ], - "time": "2026-06-02T12:23:43+00:00" + "time": "2026-07-08T15:48:39+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.11.0", + "version": "2.13.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f" + "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/bbb5e61349fa5cb822b3e87842b951088b76b81f", - "reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4", + "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4", "shasum": "" }, "require": { @@ -1614,7 +1610,7 @@ "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", @@ -1695,7 +1691,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.11.0" + "source": "https://github.com/guzzle/psr7/tree/2.13.0" }, "funding": [ { @@ -1711,25 +1707,25 @@ "type": "tidelift" } ], - "time": "2026-06-02T12:30:48+00:00" + "time": "2026-07-16T22:23:49+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.6", + "version": "v1.0.10", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "eef7f87bab6f204eba3c39224d8075c70c637946" + "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/eef7f87bab6f204eba3c39224d8075c70c637946", - "reference": "eef7f87bab6f204eba3c39224d8075c70c637946", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/f6c24c21f42b990e9a58912b332d0874df6ba839", + "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -1781,7 +1777,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.6" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.10" }, "funding": [ { @@ -1797,7 +1793,7 @@ "type": "tidelift" } ], - "time": "2026-05-23T22:00:21+00:00" + "time": "2026-07-17T13:53:03+00:00" }, { "name": "laravel/ai", @@ -1930,20 +1926,20 @@ }, { "name": "laravel/framework", - "version": "v13.14.0", + "version": "v13.23.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e60b1c817a9ef7da319e4007de6cfda5301a58c0" + "reference": "92a707229148e57f08a249211c8a5a194159c619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e60b1c817a9ef7da319e4007de6cfda5301a58c0", - "reference": "e60b1c817a9ef7da319e4007de6cfda5301a58c0", + "url": "https://api.github.com/repos/laravel/framework/zipball/92a707229148e57f08a249211c8a5a194159c619", + "reference": "92a707229148e57f08a249211c8a5a194159c619", "shasum": "" }, "require": { - "brick/math": "^0.14.2 || ^0.15 || ^0.16 || ^0.17", + "brick/math": "^0.14.2 || ^0.15 || ^0.16 || ^0.17 || ^0.18", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -1965,7 +1961,7 @@ "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", - "monolog/monolog": "^3.0", + "monolog/monolog": "^3.10", "nesbot/carbon": "^3.8.4", "nunomaduro/termwind": "^2.0", "php": "^8.3", @@ -2018,6 +2014,7 @@ "illuminate/filesystem": "self.version", "illuminate/hashing": "self.version", "illuminate/http": "self.version", + "illuminate/image": "self.version", "illuminate/json-schema": "self.version", "illuminate/log": "self.version", "illuminate/macroable": "self.version", @@ -2044,6 +2041,7 @@ "ext-gmp": "*", "fakerphp/faker": "^1.24", "guzzlehttp/psr7": "^2.9", + "intervention/image": "^4.0", "laravel/pint": "^1.18", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", @@ -2080,6 +2078,7 @@ "ext-redis": "Required to use the Redis cache and queue drivers (^4.0 || ^5.0 || ^6.0).", "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "intervention/image": "Required to use the image processing features (^4.0).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", @@ -2150,20 +2149,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-06-04T18:46:35+00:00" + "time": "2026-07-27T14:48:58+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.18", + "version": "v0.3.21", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "a19af51bb144bf87f08397921fa619f85c7d4e72" + "reference": "7753c65c281c2550c7c183f14e18062073b7d821" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/a19af51bb144bf87f08397921fa619f85c7d4e72", - "reference": "a19af51bb144bf87f08397921fa619f85c7d4e72", + "url": "https://api.github.com/repos/laravel/prompts/zipball/7753c65c281c2550c7c183f14e18062073b7d821", + "reference": "7753c65c281c2550c7c183f14e18062073b7d821", "shasum": "" }, "require": { @@ -2207,22 +2206,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.18" + "source": "https://github.com/laravel/prompts/tree/v0.3.21" }, - "time": "2026-05-19T00:47:18+00:00" + "time": "2026-06-26T00:11:25+00:00" }, { "name": "laravel/sanctum", - "version": "v4.3.2", + "version": "v4.3.3", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "2a9bccc18e9907808e0018dd15fa643937886b1e" + "reference": "fee27a573d1a013af3721d86153a65e0b11927e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/2a9bccc18e9907808e0018dd15fa643937886b1e", - "reference": "2a9bccc18e9907808e0018dd15fa643937886b1e", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/fee27a573d1a013af3721d86153a65e0b11927e6", + "reference": "fee27a573d1a013af3721d86153a65e0b11927e6", "shasum": "" }, "require": { @@ -2272,20 +2271,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2026-04-30T11:46:25+00:00" + "time": "2026-06-23T18:26:55+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.13", + "version": "v2.0.15", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce" + "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b566ee0dd251f3c4078bed003a7ce015f5ea6dce", - "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/dccd8bcb851bb03fcc005df650b708b57cc52661", + "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661", "shasum": "" }, "require": { @@ -2333,7 +2332,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-04-16T14:03:50+00:00" + "time": "2026-07-21T16:49:22+00:00" }, { "name": "laravel/tinker", @@ -2406,16 +2405,16 @@ }, { "name": "league/commonmark", - "version": "2.8.2", + "version": "2.8.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "59fb075d2101740c337c7216e3f32b36c204218b" + "reference": "1902f60f984235023acbe03db6ad614a37b3c3e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b", - "reference": "59fb075d2101740c337c7216e3f32b36c204218b", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/1902f60f984235023acbe03db6ad614a37b3c3e7", + "reference": "1902f60f984235023acbe03db6ad614a37b3c3e7", "shasum": "" }, "require": { @@ -2437,8 +2436,8 @@ "github/gfm": "0.29.0", "michelf/php-markdown": "^1.4 || ^2.0", "nyholm/psr7": "^1.5", - "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "phpstan/phpstan": "^2.0.0", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0 || ^12.0.0 || ^13.0.0", "scrutinizer/ocular": "^1.8.1", "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", @@ -2509,7 +2508,7 @@ "type": "tidelift" } ], - "time": "2026-03-19T13:16:38+00:00" + "time": "2026-07-12T15:29:16+00:00" }, { "name": "league/config", @@ -2595,16 +2594,16 @@ }, { "name": "league/flysystem", - "version": "3.34.0", + "version": "3.35.2", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e" + "reference": "b277b5dc3d56650b68904117124e79c851e12376" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e", - "reference": "2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b277b5dc3d56650b68904117124e79c851e12376", + "reference": "b277b5dc3d56650b68904117124e79c851e12376", "shasum": "" }, "require": { @@ -2672,9 +2671,9 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.34.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.35.2" }, - "time": "2026-05-14T10:28:08+00:00" + "time": "2026-07-06T14:42:07+00:00" }, { "name": "league/flysystem-local", @@ -2797,16 +2796,16 @@ }, { "name": "league/mime-type-detection", - "version": "1.16.0", + "version": "1.17.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", - "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/f5f47eff7c48ed1003069a2ca67f316fb4021c76", + "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76", "shasum": "" }, "require": { @@ -2816,7 +2815,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0" }, "type": "library", "autoload": { @@ -2837,7 +2836,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.17.0" }, "funding": [ { @@ -2849,7 +2848,7 @@ "type": "tidelift" } ], - "time": "2024-09-21T08:32:55+00:00" + "time": "2026-07-09T11:49:27+00:00" }, { "name": "league/uri", @@ -3035,16 +3034,16 @@ }, { "name": "livewire/livewire", - "version": "v4.3.1", + "version": "v4.3.4", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "6a9dd03f45a4b200abfd0ff644745b23fa7baaaa" + "reference": "e6c8d631e9687fbdd5c2bb7be9d7a5d699cce0e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/6a9dd03f45a4b200abfd0ff644745b23fa7baaaa", - "reference": "6a9dd03f45a4b200abfd0ff644745b23fa7baaaa", + "url": "https://api.github.com/repos/livewire/livewire/zipball/e6c8d631e9687fbdd5c2bb7be9d7a5d699cce0e2", + "reference": "e6c8d631e9687fbdd5c2bb7be9d7a5d699cce0e2", "shasum": "" }, "require": { @@ -3099,7 +3098,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v4.3.1" + "source": "https://github.com/livewire/livewire/tree/v4.3.4" }, "funding": [ { @@ -3107,7 +3106,7 @@ "type": "github" } ], - "time": "2026-06-02T08:58:52+00:00" + "time": "2026-07-31T00:19:18+00:00" }, { "name": "maatwebsite/excel", @@ -3115,34 +3114,33 @@ "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "a31cc13f5ef07fda91893ad3820d1e54d09cb99d" + "reference": "a9a16f1d23fc28dba9db81572054dfaca63dd6cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/a31cc13f5ef07fda91893ad3820d1e54d09cb99d", - "reference": "a31cc13f5ef07fda91893ad3820d1e54d09cb99d", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/a9a16f1d23fc28dba9db81572054dfaca63dd6cc", + "reference": "a9a16f1d23fc28dba9db81572054dfaca63dd6cc", "shasum": "" }, "require": { - "composer/semver": "^3.3", + "composer/semver": "^3.4", "illuminate/support": "^12.0 || ^13.0", "php": "^8.3", - "phpoffice/phpspreadsheet": "^5.3", + "phpoffice/phpspreadsheet": "^5.8", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { - "brianium/paratest": "^7.19 || ^8.0", - "driftingly/rector-laravel": "^2.3", + "brianium/paratest": "^7.20", + "driftingly/rector-laravel": "^2.5", "ext-sqlite3": "*", - "larastan/larastan": "^3.9", - "laravel/pint": "^1.0", - "laravel/scout": "^10.0 || ^11.0", - "orchestra/testbench": "^10.0 || ^11.0", + "larastan/larastan": "^3.10", + "laravel/pint": "^1.29", + "laravel/scout": "^10.25 || ^11.2", + "orchestra/testbench": "^10.11 || ^11.1", "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.1.55", "phpstan/phpstan-mockery": "^2.0", - "phpunit/phpunit": "^12.5.3 || ^13.0.0", - "predis/predis": "^1.1", + "phpunit/phpunit": "^12.5 || ~13.1.14", + "predis/predis": "^2.3 || ^3.0", "rector/rector": "^2.4.2" }, "type": "library", @@ -3197,7 +3195,7 @@ "type": "github" } ], - "time": "2026-06-01T17:23:34+00:00" + "time": "2026-07-10T20:00:43+00:00" }, { "name": "maennchen/zipstream-php", @@ -3386,16 +3384,16 @@ }, { "name": "masterminds/html5", - "version": "2.10.0", + "version": "2.10.1", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "fcf91eb64359852f00d921887b219479b4f21251" + "reference": "fd5018f6815fff903946d0564977b44ce8010e29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", - "reference": "fcf91eb64359852f00d921887b219479b4f21251", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fd5018f6815fff903946d0564977b44ce8010e29", + "reference": "fd5018f6815fff903946d0564977b44ce8010e29", "shasum": "" }, "require": { @@ -3403,7 +3401,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9 || ^10" }, "type": "library", "extra": { @@ -3447,9 +3445,9 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.10.1" }, - "time": "2025-07-25T09:04:22+00:00" + "time": "2026-06-23T18:43:15+00:00" }, { "name": "monolog/monolog", @@ -3556,16 +3554,16 @@ }, { "name": "mtdowling/jmespath.php", - "version": "2.8.0", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + "reference": "2157c5e50e813ec6a96c1eed3be7f64a20fb32a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", - "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/2157c5e50e813ec6a96c1eed3be7f64a20fb32a8", + "reference": "2157c5e50e813ec6a96c1eed3be7f64a20fb32a8", "shasum": "" }, "require": { @@ -3574,7 +3572,7 @@ }, "require-dev": { "composer/xdebug-handler": "^3.0.3", - "phpunit/phpunit": "^8.5.33" + "phpunit/phpunit": "^8.5.52" }, "bin": [ "bin/jp.php" @@ -3582,7 +3580,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.9-dev" } }, "autoload": { @@ -3616,22 +3614,22 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + "source": "https://github.com/jmespath/jmespath.php/tree/2.9.2" }, - "time": "2024-09-04T18:46:31+00:00" + "time": "2026-07-06T18:56:19+00:00" }, { "name": "nesbot/carbon", - "version": "3.11.4", + "version": "3.13.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60" + "reference": "2937ad3d1d2c506fd2bc97d571438a95641f44e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/e890471a3494740f7d9326d72ce6a8c559ffee60", - "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/2937ad3d1d2c506fd2bc97d571438a95641f44e2", + "reference": "2937ad3d1d2c506fd2bc97d571438a95641f44e2", "shasum": "" }, "require": { @@ -3723,7 +3721,7 @@ "type": "tidelift" } ], - "time": "2026-04-07T09:57:54+00:00" + "time": "2026-07-09T18:23:49+00:00" }, { "name": "nette/schema", @@ -3794,16 +3792,16 @@ }, { "name": "nette/utils", - "version": "v4.1.4", + "version": "v4.1.5", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" + "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", + "url": "https://api.github.com/repos/nette/utils/zipball/b043439dbdf954e6c28b5ea7e34b0100f83165e0", + "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0", "shasum": "" }, "require": { @@ -3823,7 +3821,7 @@ }, "suggest": { "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-iconv": "to use Strings::chr(), ord() and reverse()", "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", @@ -3879,26 +3877,25 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.4" + "source": "https://github.com/nette/utils/tree/v4.1.5" }, - "time": "2026-05-11T20:49:54+00:00" + "time": "2026-07-17T23:02:45+00:00" }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" @@ -3937,9 +3934,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2026-07-04T14:30:18+00:00" }, { "name": "nunomaduro/termwind", @@ -4030,16 +4027,16 @@ }, { "name": "openspout/openspout", - "version": "v5.7.2", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/openspout/openspout.git", - "reference": "f383ae8ab4c735b6a6a0cef396e9799900584f3e" + "reference": "1e1aad228e3e289c7e11d97b07496f2569121afc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/openspout/openspout/zipball/f383ae8ab4c735b6a6a0cef396e9799900584f3e", - "reference": "f383ae8ab4c735b6a6a0cef396e9799900584f3e", + "url": "https://api.github.com/repos/openspout/openspout/zipball/1e1aad228e3e289c7e11d97b07496f2569121afc", + "reference": "1e1aad228e3e289c7e11d97b07496f2569121afc", "shasum": "" }, "require": { @@ -4053,13 +4050,13 @@ "require-dev": { "ext-fileinfo": "*", "ext-zlib": "*", - "friendsofphp/php-cs-fixer": "^3.95.2", - "infection/infection": "^0.33.2", - "phpbench/phpbench": "^1.6.1", - "phpstan/phpstan": "^2.2.1", - "phpstan/phpstan-phpunit": "^2.0.16", + "friendsofphp/php-cs-fixer": "^3.95.14", + "infection/infection": "^0.34", + "phpbench/phpbench": "^1.7.0", + "phpstan/phpstan": "^2.2.5", + "phpstan/phpstan-phpunit": "^2.0.18", "phpstan/phpstan-strict-rules": "^2.0.11", - "phpunit/phpunit": "^13.1.13" + "phpunit/phpunit": "^13.2.4" }, "suggest": { "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", @@ -4107,7 +4104,7 @@ ], "support": { "issues": "https://github.com/openspout/openspout/issues", - "source": "https://github.com/openspout/openspout/tree/v5.7.2" + "source": "https://github.com/openspout/openspout/tree/v5.8.0" }, "funding": [ { @@ -4119,20 +4116,20 @@ "type": "github" } ], - "time": "2026-05-29T11:43:33+00:00" + "time": "2026-07-15T07:34:50+00:00" }, { "name": "owen-it/laravel-auditing", - "version": "v14.0.3", + "version": "v14.0.6", "source": { "type": "git", "url": "https://github.com/owen-it/laravel-auditing.git", - "reference": "34e8a21890082a7a353894a4acdeb2d301dbe0d4" + "reference": "31b73b73e73888bc6a7c307805fb22f7d653639f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/owen-it/laravel-auditing/zipball/34e8a21890082a7a353894a4acdeb2d301dbe0d4", - "reference": "34e8a21890082a7a353894a4acdeb2d301dbe0d4", + "url": "https://api.github.com/repos/owen-it/laravel-auditing/zipball/31b73b73e73888bc6a7c307805fb22f7d653639f", + "reference": "31b73b73e73888bc6a7c307805fb22f7d653639f", "shasum": "" }, "require": { @@ -4145,7 +4142,7 @@ "require-dev": { "mockery/mockery": "^1.5.1", "orchestra/testbench": "^9.0|^10.0|^11.0", - "phpunit/phpunit": "^11.0|^12.5.12" + "phpunit/phpunit": "^11.5|^12.5.12" }, "type": "package", "extra": { @@ -4203,20 +4200,20 @@ "issues": "https://github.com/owen-it/laravel-auditing/issues", "source": "https://github.com/owen-it/laravel-auditing" }, - "time": "2026-03-27T13:27:17+00:00" + "time": "2026-06-20T14:28:21+00:00" }, { "name": "phpoffice/phpspreadsheet", - "version": "5.8.0", + "version": "5.9.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "01964d92536edf1a3a874b9580a52824bebf6fbb" + "reference": "05e99ebf61238a70227b4d9cc02d0030d34f6339" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/01964d92536edf1a3a874b9580a52824bebf6fbb", - "reference": "01964d92536edf1a3a874b9580a52824bebf6fbb", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/05e99ebf61238a70227b4d9cc02d0030d34f6339", + "reference": "05e99ebf61238a70227b4d9cc02d0030d34f6339", "shasum": "" }, "require": { @@ -4238,7 +4235,7 @@ "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", - "php": "^8.1", + "php": "^8.2", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { @@ -4252,7 +4249,7 @@ "phpstan/phpstan": "^1.1 || ^2.0", "phpstan/phpstan-deprecation-rules": "^1.0 || ^2.0", "phpstan/phpstan-phpunit": "^1.0 || ^2.0", - "phpunit/phpunit": "^10.5", + "phpunit/phpunit": "^10.5 || ^11.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -4310,9 +4307,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.8.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.9.0" }, - "time": "2026-06-07T03:51:10+00:00" + "time": "2026-07-12T19:17:39+00:00" }, { "name": "phpoption/phpoption", @@ -4803,16 +4800,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.23", + "version": "v0.12.24", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "4dcc0f08047d52bbde475eda481146fd8e27e1a4" + "reference": "ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4dcc0f08047d52bbde475eda481146fd8e27e1a4", - "reference": "4dcc0f08047d52bbde475eda481146fd8e27e1a4", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1", + "reference": "ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1", "shasum": "" }, "require": { @@ -4876,9 +4873,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.23" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.24" }, - "time": "2026-05-23T13:41:31+00:00" + "time": "2026-06-29T15:41:09+00:00" }, { "name": "ralouphie/getallheaders", @@ -5002,20 +4999,20 @@ }, { "name": "ramsey/uuid", - "version": "4.9.2", + "version": "4.9.3", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "8429c78ca35a09f27565311b98101e2826affde0" + "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", - "reference": "8429c78ca35a09f27565311b98101e2826affde0", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/1df15849d00943a67d677dc9cfd80795f038c9f8", + "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8", "shasum": "" }, "require": { - "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "brick/math": ">=0.8.16 <=0.18", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -5074,22 +5071,22 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.2" + "source": "https://github.com/ramsey/uuid/tree/4.9.3" }, - "time": "2025-12-14T04:43:48+00:00" + "time": "2026-06-18T03:57:49+00:00" }, { "name": "sabberworm/php-css-parser", - "version": "v9.3.0", + "version": "v9.4.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949" + "reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", - "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f", + "reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f", "shasum": "" }, "require": { @@ -5100,15 +5097,15 @@ "require-dev": { "php-parallel-lint/php-parallel-lint": "1.4.0", "phpstan/extension-installer": "1.4.3", - "phpstan/phpstan": "1.12.32 || 2.1.32", - "phpstan/phpstan-phpunit": "1.4.2 || 2.0.8", - "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.7", + "phpstan/phpstan": "1.12.33 || 2.2.2", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.16", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.11", "phpunit/phpunit": "8.5.52", "rawr/phpunit-data-provider": "3.3.1", - "rector/rector": "1.2.10 || 2.2.8", - "rector/type-perfect": "1.0.0 || 2.1.0", + "rector/rector": "1.2.10 || 2.4.6", + "rector/type-perfect": "1.0.0 || 2.1.3", "squizlabs/php_codesniffer": "4.0.1", - "thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.1" + "thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.3" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" @@ -5116,7 +5113,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.4.x-dev" + "dev-main": "9.5.x-dev" } }, "autoload": { @@ -5154,22 +5151,22 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.4.0" }, - "time": "2026-03-03T17:31:43+00:00" + "time": "2026-06-18T15:10:53+00:00" }, { "name": "secondnetwork/blade-tabler-icons", - "version": "v3.44.0", + "version": "v3.46.0", "source": { "type": "git", "url": "https://github.com/secondnetwork/blade-tabler-icons.git", - "reference": "856ad75e2c0704096bf4a708b6464620e41d1a34" + "reference": "aedaebc18f382a9d0a1870e9ad394c5c89abd72b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/secondnetwork/blade-tabler-icons/zipball/856ad75e2c0704096bf4a708b6464620e41d1a34", - "reference": "856ad75e2c0704096bf4a708b6464620e41d1a34", + "url": "https://api.github.com/repos/secondnetwork/blade-tabler-icons/zipball/aedaebc18f382a9d0a1870e9ad394c5c89abd72b", + "reference": "aedaebc18f382a9d0a1870e9ad394c5c89abd72b", "shasum": "" }, "require": { @@ -5212,9 +5209,9 @@ ], "support": { "issues": "https://github.com/secondnetwork/blade-tabler-icons/issues", - "source": "https://github.com/secondnetwork/blade-tabler-icons/tree/v3.44.0" + "source": "https://github.com/secondnetwork/blade-tabler-icons/tree/v3.46.0" }, - "time": "2026-05-11T14:36:11+00:00" + "time": "2026-07-30T13:49:44+00:00" }, { "name": "spatie/db-dumper", @@ -5282,16 +5279,16 @@ }, { "name": "spatie/laravel-backup", - "version": "10.2.2", + "version": "10.3.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-backup.git", - "reference": "fd8ae12e6a8401dd4de6d3beb5f37d9a627064f3" + "reference": "1160cf6a6faa262586f47e2bd20c59512bb1a77e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/fd8ae12e6a8401dd4de6d3beb5f37d9a627064f3", - "reference": "fd8ae12e6a8401dd4de6d3beb5f37d9a627064f3", + "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/1160cf6a6faa262586f47e2bd20c59512bb1a77e", + "reference": "1160cf6a6faa262586f47e2bd20c59512bb1a77e", "shasum": "" }, "require": { @@ -5366,7 +5363,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-backup/issues", - "source": "https://github.com/spatie/laravel-backup/tree/10.2.2" + "source": "https://github.com/spatie/laravel-backup/tree/10.3.1" }, "funding": [ { @@ -5378,7 +5375,7 @@ "type": "other" } ], - "time": "2026-06-01T22:44:58+00:00" + "time": "2026-07-28T13:19:06+00:00" }, { "name": "spatie/laravel-package-tools", @@ -5683,16 +5680,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.3.1", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "662e481d6ec07ef29fd05010433428851a42cd07" + "reference": "32cbb9645b28839cf4f476708e99a2c70e6802c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/662e481d6ec07ef29fd05010433428851a42cd07", - "reference": "662e481d6ec07ef29fd05010433428851a42cd07", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/32cbb9645b28839cf4f476708e99a2c70e6802c9", + "reference": "32cbb9645b28839cf4f476708e99a2c70e6802c9", "shasum": "" }, "require": { @@ -5728,7 +5725,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.3.1" + "source": "https://github.com/spatie/temporary-directory/tree/2.4.0" }, "funding": [ { @@ -5740,7 +5737,7 @@ "type": "github" } ], - "time": "2026-01-12T07:42:22+00:00" + "time": "2026-06-22T07:55:44+00:00" }, { "name": "symfony/clock", @@ -5821,16 +5818,16 @@ }, { "name": "symfony/console", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f5a856c6ecb56b3c21ed94a5b7bf940d857d110a" + "reference": "535e18a1b8925f6c01a55b171d157ab66c2ace15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f5a856c6ecb56b3c21ed94a5b7bf940d857d110a", - "reference": "f5a856c6ecb56b3c21ed94a5b7bf940d857d110a", + "url": "https://api.github.com/repos/symfony/console/zipball/535e18a1b8925f6c01a55b171d157ab66c2ace15", + "reference": "535e18a1b8925f6c01a55b171d157ab66c2ace15", "shasum": "" }, "require": { @@ -5897,7 +5894,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v8.1.0" + "source": "https://github.com/symfony/console/tree/v8.1.2" }, "funding": [ { @@ -5917,7 +5914,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-27T13:58:19+00:00" }, { "name": "symfony/css-selector", @@ -5990,16 +5987,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", - "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { @@ -6037,7 +6034,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" }, "funding": [ { @@ -6057,20 +6054,20 @@ "type": "tidelift" } ], - "time": "2026-04-13T15:52:40+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/error-handler", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "d8aeb1abd3fef84795567850d3a567bdb5945ee5" + "reference": "dc98404be5e8c949815e23fee1928f5de4f3f5d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/d8aeb1abd3fef84795567850d3a567bdb5945ee5", - "reference": "d8aeb1abd3fef84795567850d3a567bdb5945ee5", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/dc98404be5e8c949815e23fee1928f5de4f3f5d3", + "reference": "dc98404be5e8c949815e23fee1928f5de4f3f5d3", "shasum": "" }, "require": { @@ -6118,7 +6115,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v8.1.0" + "source": "https://github.com/symfony/error-handler/tree/v8.1.2" }, "funding": [ { @@ -6138,20 +6135,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102" + "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f249ae3f680958b6f1f9dd76e5747cf0695b4102", - "reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c14c05a9e6da7f5e375e6efc28952c7e7dbddffb", + "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb", "shasum": "" }, "require": { @@ -6204,7 +6201,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.2" }, "funding": [ { @@ -6224,20 +6221,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", - "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e", + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e", "shasum": "" }, "require": { @@ -6284,7 +6281,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1" }, "funding": [ { @@ -6304,20 +6301,20 @@ "type": "tidelift" } ], - "time": "2026-01-05T13:30:16+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/filesystem", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2" + "reference": "17856b7a222664a26a5ea1cb06ee0721c2438217" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/99aec13b82b4967ec5088222c4a3ecca955949c2", - "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/17856b7a222664a26a5ea1cb06ee0721c2438217", + "reference": "17856b7a222664a26a5ea1cb06ee0721c2438217", "shasum": "" }, "require": { @@ -6355,7 +6352,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v8.1.0" + "source": "https://github.com/symfony/filesystem/tree/v8.1.2" }, "funding": [ { @@ -6375,20 +6372,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/finder", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "58d2e767a66052c1487356f953445634a8194c64" + "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/58d2e767a66052c1487356f953445634a8194c64", - "reference": "58d2e767a66052c1487356f953445634a8194c64", + "url": "https://api.github.com/repos/symfony/finder/zipball/e2989e762c70f9490fa3a00a0ac0fae5aa97a531", + "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531", "shasum": "" }, "require": { @@ -6423,7 +6420,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.1.0" + "source": "https://github.com/symfony/finder/tree/v8.1.1" }, "funding": [ { @@ -6443,20 +6440,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-27T09:05:56+00:00" }, { "name": "symfony/http-foundation", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "af11474600f06718086c2cda4fa6fa8d0a672e7e" + "reference": "9943adbf5a64e2951a8d9eb0485310d55624f0e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/af11474600f06718086c2cda4fa6fa8d0a672e7e", - "reference": "af11474600f06718086c2cda4fa6fa8d0a672e7e", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9943adbf5a64e2951a8d9eb0485310d55624f0e8", + "reference": "9943adbf5a64e2951a8d9eb0485310d55624f0e8", "shasum": "" }, "require": { @@ -6504,7 +6501,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v8.1.0" + "source": "https://github.com/symfony/http-foundation/tree/v8.1.2" }, "funding": [ { @@ -6524,20 +6521,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-29T07:22:54+00:00" }, { "name": "symfony/http-kernel", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "cefeb37c82eed3e0c42fa25ba64cd3a908d90f39" + "reference": "c7bb08dc26a7a7da68fb7ac1ce9de925e6464dbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cefeb37c82eed3e0c42fa25ba64cd3a908d90f39", - "reference": "cefeb37c82eed3e0c42fa25ba64cd3a908d90f39", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c7bb08dc26a7a7da68fb7ac1ce9de925e6464dbc", + "reference": "c7bb08dc26a7a7da68fb7ac1ce9de925e6464dbc", "shasum": "" }, "require": { @@ -6553,6 +6550,7 @@ "symfony/dependency-injection": "<8.1", "symfony/flex": "<2.10", "symfony/http-client-contracts": "<2.5", + "symfony/serializer": "<7.4.15|>=8.0,<8.0.15|>=8.1,<8.1.2", "symfony/translation-contracts": "<2.5", "symfony/var-dumper": "<8.1", "symfony/web-profiler-bundle": "<8.1", @@ -6585,7 +6583,7 @@ "symfony/validator": "^7.4|^8.0", "symfony/var-dumper": "^8.1", "symfony/var-exporter": "^7.4|^8.0", - "twig/twig": "^3.21" + "twig/twig": "^3.21|^4.0" }, "type": "library", "autoload": { @@ -6613,7 +6611,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v8.1.0" + "source": "https://github.com/symfony/http-kernel/tree/v8.1.2" }, "funding": [ { @@ -6633,20 +6631,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T08:46:08+00:00" + "time": "2026-07-29T11:54:54+00:00" }, { "name": "symfony/mailer", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "9418d772df3a03a142e3bc06f602adb2b8724877" + "reference": "221c7f326ace1ac2baee8331d829d5b7f04f4d53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/9418d772df3a03a142e3bc06f602adb2b8724877", - "reference": "9418d772df3a03a142e3bc06f602adb2b8724877", + "url": "https://api.github.com/repos/symfony/mailer/zipball/221c7f326ace1ac2baee8331d829d5b7f04f4d53", + "reference": "221c7f326ace1ac2baee8331d829d5b7f04f4d53", "shasum": "" }, "require": { @@ -6693,7 +6691,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v8.1.0" + "source": "https://github.com/symfony/mailer/tree/v8.1.2" }, "funding": [ { @@ -6713,20 +6711,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-28T07:35:25+00:00" }, { "name": "symfony/mime", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b164ae7e3f7915aacfe9ee155f2f358502440664" + "reference": "75f4779d4ec2e13f24a3a7e5d0347c340c7ca627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b164ae7e3f7915aacfe9ee155f2f358502440664", - "reference": "b164ae7e3f7915aacfe9ee155f2f358502440664", + "url": "https://api.github.com/repos/symfony/mime/zipball/75f4779d4ec2e13f24a3a7e5d0347c340c7ca627", + "reference": "75f4779d4ec2e13f24a3a7e5d0347c340c7ca627", "shasum": "" }, "require": { @@ -6779,7 +6777,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v8.1.0" + "source": "https://github.com/symfony/mime/tree/v8.1.2" }, "funding": [ { @@ -6799,20 +6797,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-29T08:00:47+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.38.1", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "e9247d281d694a5120554d9afaf54e070e88a603" + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", - "reference": "e9247d281d694a5120554d9afaf54e070e88a603", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "shasum": "" }, "require": { @@ -6861,7 +6859,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" }, "funding": [ { @@ -6881,7 +6879,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T05:58:03+00:00" + "time": "2026-07-28T08:25:59+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -7136,16 +7134,16 @@ }, { "name": "symfony/polyfill-php85", - "version": "v1.38.1", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1" + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", - "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", "shasum": "" }, "require": { @@ -7192,7 +7190,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" }, "funding": [ { @@ -7212,20 +7210,20 @@ "type": "tidelift" } ], - "time": "2026-05-26T02:25:22+00:00" + "time": "2026-07-01T12:47:55+00:00" }, { "name": "symfony/polyfill-php86", - "version": "v1.38.0", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php86.git", - "reference": "fcec68d64f46dc84e1f6ffcf2c6dda40ff3143ad" + "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/fcec68d64f46dc84e1f6ffcf2c6dda40ff3143ad", - "reference": "fcec68d64f46dc84e1f6ffcf2c6dda40ff3143ad", + "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/6bc356ed3d8dbfeea8f0de235e34d670704e880e", + "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e", "shasum": "" }, "require": { @@ -7272,7 +7270,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php86/tree/v1.38.0" + "source": "https://github.com/symfony/polyfill-php86/tree/v1.41.0" }, "funding": [ { @@ -7292,7 +7290,7 @@ "type": "tidelift" } ], - "time": "2026-05-25T11:52:35+00:00" + "time": "2026-07-02T13:42:24+00:00" }, { "name": "symfony/polyfill-uuid", @@ -7444,16 +7442,16 @@ }, { "name": "symfony/routing", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3" + "reference": "1058d4e13bb81dd9a6f7565686df7e13b880cdbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3", - "reference": "fe0bfec72c8a806109fb9c3a5f2b898fe0c76eb3", + "url": "https://api.github.com/repos/symfony/routing/zipball/1058d4e13bb81dd9a6f7565686df7e13b880cdbd", + "reference": "1058d4e13bb81dd9a6f7565686df7e13b880cdbd", "shasum": "" }, "require": { @@ -7500,7 +7498,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v8.1.0" + "source": "https://github.com/symfony/routing/tree/v8.1.2" }, "funding": [ { @@ -7520,20 +7518,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" + "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", - "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", + "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", "shasum": "" }, "require": { @@ -7587,7 +7585,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.1" }, "funding": [ { @@ -7607,20 +7605,20 @@ "type": "tidelift" } ], - "time": "2026-03-28T09:44:51+00:00" + "time": "2026-06-16T09:55:08+00:00" }, { "name": "symfony/string", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9" + "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9", - "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9", + "url": "https://api.github.com/repos/symfony/string/zipball/286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc", + "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc", "shasum": "" }, "require": { @@ -7677,7 +7675,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v8.1.0" + "source": "https://github.com/symfony/string/tree/v8.1.2" }, "funding": [ { @@ -7697,20 +7695,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-28T07:35:25+00:00" }, { "name": "symfony/translation", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b2bd012ca28c4acae830ee1206a5b6e35dd99693" + "reference": "342b4218630dc2cf284cedcb2080c80b13404014" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b2bd012ca28c4acae830ee1206a5b6e35dd99693", - "reference": "b2bd012ca28c4acae830ee1206a5b6e35dd99693", + "url": "https://api.github.com/repos/symfony/translation/zipball/342b4218630dc2cf284cedcb2080c80b13404014", + "reference": "342b4218630dc2cf284cedcb2080c80b13404014", "shasum": "" }, "require": { @@ -7770,7 +7768,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v8.1.0" + "source": "https://github.com/symfony/translation/tree/v8.1.1" }, "funding": [ { @@ -7790,20 +7788,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-06T11:11:44+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621", + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621", "shasum": "" }, "require": { @@ -7852,7 +7850,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1" }, "funding": [ { @@ -7872,7 +7870,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T13:30:16+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/uid", @@ -7954,16 +7952,16 @@ }, { "name": "symfony/var-dumper", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c2c4df1d21477cc21c9f6dc1b14d07c3abc4963e" + "reference": "865103cf742a039f34645b971fc3ace308d6c167" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c2c4df1d21477cc21c9f6dc1b14d07c3abc4963e", - "reference": "c2c4df1d21477cc21c9f6dc1b14d07c3abc4963e", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/865103cf742a039f34645b971fc3ace308d6c167", + "reference": "865103cf742a039f34645b971fc3ace308d6c167", "shasum": "" }, "require": { @@ -7979,7 +7977,7 @@ "symfony/http-kernel": "^7.4|^8.0", "symfony/process": "^7.4|^8.0", "symfony/uid": "^7.4|^8.0", - "twig/twig": "^3.12" + "twig/twig": "^3.12|^4.0" }, "bin": [ "Resources/bin/var-dump-server" @@ -8017,7 +8015,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v8.1.0" + "source": "https://github.com/symfony/var-dumper/tree/v8.1.2" }, "funding": [ { @@ -8037,7 +8035,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "thecodingmachine/safe", @@ -8184,16 +8182,16 @@ }, { "name": "tightenco/ziggy", - "version": "v2.6.2", + "version": "v2.6.3", "source": { "type": "git", "url": "https://github.com/tighten/ziggy.git", - "reference": "8a0b645921623f77dceaf543d61ecd51a391d96e" + "reference": "14c5744f155182188419f7729d96e0ed7225e73b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/8a0b645921623f77dceaf543d61ecd51a391d96e", - "reference": "8a0b645921623f77dceaf543d61ecd51a391d96e", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/14c5744f155182188419f7729d96e0ed7225e73b", + "reference": "14c5744f155182188419f7729d96e0ed7225e73b", "shasum": "" }, "require": { @@ -8203,7 +8201,7 @@ }, "require-dev": { "laravel/folio": "^1.1", - "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0 || ^11.0", "pestphp/pest": "^2.0 || ^3.0 || ^4.0", "pestphp/pest-plugin-laravel": "^2.0 || ^3.0 || ^4.0" }, @@ -8248,9 +8246,9 @@ ], "support": { "issues": "https://github.com/tighten/ziggy/issues", - "source": "https://github.com/tighten/ziggy/tree/v2.6.2" + "source": "https://github.com/tighten/ziggy/tree/v2.6.3" }, - "time": "2026-03-05T14:41:19+00:00" + "time": "2026-06-23T21:57:52+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -8378,16 +8376,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.3", + "version": "v5.6.4", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "955e7815d677a3eaa7075231212f2110983adecc" + "reference": "416df702837983f8d5ff48c9c3fee4f5f57b980b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", - "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/416df702837983f8d5ff48c9c3fee4f5f57b980b", + "reference": "416df702837983f8d5ff48c9c3fee4f5f57b980b", "shasum": "" }, "require": { @@ -8446,7 +8444,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.4" }, "funding": [ { @@ -8458,7 +8456,7 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:49:13+00:00" + "time": "2026-07-06T19:11:50+00:00" }, { "name": "voku/portable-ascii", @@ -8536,16 +8534,16 @@ }, { "name": "webmozart/assert", - "version": "2.4.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155" + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155", - "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70", "shasum": "" }, "require": { @@ -8596,9 +8594,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.4.0" + "source": "https://github.com/webmozarts/assert/tree/2.4.1" }, - "time": "2026-05-20T13:07:01+00:00" + "time": "2026-06-15T15:31:57+00:00" }, { "name": "yajra/laravel-datatables", @@ -8667,16 +8665,16 @@ }, { "name": "yajra/laravel-datatables-buttons", - "version": "v13.2.0", + "version": "v13.2.1", "source": { "type": "git", "url": "https://github.com/yajra/laravel-datatables-buttons.git", - "reference": "426346860a88f69b93a0f51a5af8290e0e4bb55b" + "reference": "d7d8f8849f24ecec3ab25c8d8c0f785dc068fac1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yajra/laravel-datatables-buttons/zipball/426346860a88f69b93a0f51a5af8290e0e4bb55b", - "reference": "426346860a88f69b93a0f51a5af8290e0e4bb55b", + "url": "https://api.github.com/repos/yajra/laravel-datatables-buttons/zipball/d7d8f8849f24ecec3ab25c8d8c0f785dc068fac1", + "reference": "d7d8f8849f24ecec3ab25c8d8c0f785dc068fac1", "shasum": "" }, "require": { @@ -8735,7 +8733,7 @@ ], "support": { "issues": "https://github.com/yajra/laravel-datatables-buttons/issues", - "source": "https://github.com/yajra/laravel-datatables-buttons/tree/v13.2.0" + "source": "https://github.com/yajra/laravel-datatables-buttons/tree/v13.2.1" }, "funding": [ { @@ -8743,7 +8741,7 @@ "type": "github" } ], - "time": "2026-03-28T09:30:37+00:00" + "time": "2026-07-21T05:19:21+00:00" }, { "name": "yajra/laravel-datatables-editor", @@ -8829,16 +8827,16 @@ }, { "name": "yajra/laravel-datatables-export", - "version": "v13.2.0", + "version": "v13.2.2", "source": { "type": "git", "url": "https://github.com/yajra/laravel-datatables-export.git", - "reference": "bb2f1ae2d3ee6793472c063f352593404a547745" + "reference": "8d9a7352c8ee5b531dd497891850bfa68a671f15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yajra/laravel-datatables-export/zipball/bb2f1ae2d3ee6793472c063f352593404a547745", - "reference": "bb2f1ae2d3ee6793472c063f352593404a547745", + "url": "https://api.github.com/repos/yajra/laravel-datatables-export/zipball/8d9a7352c8ee5b531dd497891850bfa68a671f15", + "reference": "8d9a7352c8ee5b531dd497891850bfa68a671f15", "shasum": "" }, "require": { @@ -8846,7 +8844,7 @@ "livewire/livewire": "^4.2.2", "openspout/openspout": "^4.24.5 || ^5.0", "php": "^8.3", - "phpoffice/phpspreadsheet": "^5.5", + "phpoffice/phpspreadsheet": "^5.8.1", "yajra/laravel-datatables-buttons": "^13.0.2" }, "require-dev": { @@ -8894,7 +8892,7 @@ ], "support": { "issues": "https://github.com/yajra/laravel-datatables-export/issues", - "source": "https://github.com/yajra/laravel-datatables-export/tree/v13.2.0" + "source": "https://github.com/yajra/laravel-datatables-export/tree/v13.2.2" }, "funding": [ { @@ -8902,7 +8900,7 @@ "type": "github" } ], - "time": "2026-05-28T02:36:01+00:00" + "time": "2026-07-24T02:53:16+00:00" }, { "name": "yajra/laravel-datatables-fractal", @@ -9053,16 +9051,16 @@ }, { "name": "yajra/laravel-datatables-oracle", - "version": "v13.1.2", + "version": "v13.1.5", "source": { "type": "git", "url": "https://github.com/yajra/laravel-datatables.git", - "reference": "ded9345b7c00c85ce0fe0cea40e24e61c8489e10" + "reference": "299c07a7dae380e565bd328104965b6e02286c2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/ded9345b7c00c85ce0fe0cea40e24e61c8489e10", - "reference": "ded9345b7c00c85ce0fe0cea40e24e61c8489e10", + "url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/299c07a7dae380e565bd328104965b6e02286c2f", + "reference": "299c07a7dae380e565bd328104965b6e02286c2f", "shasum": "" }, "require": { @@ -9130,7 +9128,7 @@ ], "support": { "issues": "https://github.com/yajra/laravel-datatables/issues", - "source": "https://github.com/yajra/laravel-datatables/tree/v13.1.2" + "source": "https://github.com/yajra/laravel-datatables/tree/v13.1.5" }, "funding": [ { @@ -9138,22 +9136,22 @@ "type": "github" } ], - "time": "2026-05-19T03:34:29+00:00" + "time": "2026-07-03T01:53:46+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v4.3.0", + "version": "v4.4.0", "source": { "type": "git", "url": "https://github.com/fruitcake/laravel-debugbar.git", - "reference": "3d76ea8d78b82225b92789de65fc630c1cd8e80c" + "reference": "80ef956bda9e1a5824037d6f2cd06e73092e5634" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/3d76ea8d78b82225b92789de65fc630c1cd8e80c", - "reference": "3d76ea8d78b82225b92789de65fc630c1cd8e80c", + "url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/80ef956bda9e1a5824037d6f2cd06e73092e5634", + "reference": "80ef956bda9e1a5824037d6f2cd06e73092e5634", "shasum": "" }, "require": { @@ -9161,11 +9159,12 @@ "illuminate/session": "^11|^12|^13.0", "illuminate/support": "^11|^12|^13.0", "php": "^8.2", - "php-debugbar/php-debugbar": "^3.7.2", + "php-debugbar/php-debugbar": "^3.8.0", "php-debugbar/symfony-bridge": "^1.1" }, "require-dev": { "larastan/larastan": "^3", + "laravel/ai": "^0.8", "laravel/octane": "^2", "laravel/pennant": "^1", "laravel/pint": "^1", @@ -9227,7 +9226,7 @@ ], "support": { "issues": "https://github.com/fruitcake/laravel-debugbar/issues", - "source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.3.0" + "source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.4.0" }, "funding": [ { @@ -9239,7 +9238,7 @@ "type": "github" } ], - "time": "2026-06-04T07:54:01+00:00" + "time": "2026-07-04T08:30:57+00:00" }, { "name": "barryvdh/laravel-ide-helper", @@ -9972,16 +9971,16 @@ }, { "name": "laravel/boost", - "version": "v2.4.9", + "version": "v2.4.13", "source": { "type": "git", "url": "https://github.com/laravel/boost.git", - "reference": "f0359e55f6c3782023a35baf1d3df817053d69e8" + "reference": "f55e08f5afa89ac72f23f574175005b67878f466" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/boost/zipball/f0359e55f6c3782023a35baf1d3df817053d69e8", - "reference": "f0359e55f6c3782023a35baf1d3df817053d69e8", + "url": "https://api.github.com/repos/laravel/boost/zipball/f55e08f5afa89ac72f23f574175005b67878f466", + "reference": "f55e08f5afa89ac72f23f574175005b67878f466", "shasum": "" }, "require": { @@ -9990,7 +9989,7 @@ "illuminate/contracts": "^11.45.3|^12.41.1|^13.0", "illuminate/routing": "^11.45.3|^12.41.1|^13.0", "illuminate/support": "^11.45.3|^12.41.1|^13.0", - "laravel/mcp": "^0.7.1", + "laravel/mcp": "^0.7.1|^0.8.0|^0.9.0", "laravel/prompts": "^0.3.10", "laravel/roster": "^0.5.0", "php": "^8.2" @@ -10034,20 +10033,20 @@ "issues": "https://github.com/laravel/boost/issues", "source": "https://github.com/laravel/boost" }, - "time": "2026-06-04T10:33:57+00:00" + "time": "2026-07-17T14:28:57+00:00" }, { "name": "laravel/mcp", - "version": "v0.7.2", + "version": "v0.9.1", "source": { "type": "git", "url": "https://github.com/laravel/mcp.git", - "reference": "08962a276357f89164f78b38407c08187ab26cfe" + "reference": "a08884d79a95c5143498507aec5badf751cdbec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/mcp/zipball/08962a276357f89164f78b38407c08187ab26cfe", - "reference": "08962a276357f89164f78b38407c08187ab26cfe", + "url": "https://api.github.com/repos/laravel/mcp/zipball/a08884d79a95c5143498507aec5badf751cdbec4", + "reference": "a08884d79a95c5143498507aec5badf751cdbec4", "shasum": "" }, "require": { @@ -10075,7 +10074,7 @@ "extra": { "laravel": { "aliases": { - "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" + "Mcp": "Laravel\\Mcp\\Facades\\Mcp" }, "providers": [ "Laravel\\Mcp\\Server\\McpServiceProvider" @@ -10108,7 +10107,7 @@ "issues": "https://github.com/laravel/mcp/issues", "source": "https://github.com/laravel/mcp" }, - "time": "2026-05-22T11:45:29+00:00" + "time": "2026-07-21T13:23:52+00:00" }, { "name": "laravel/pail", @@ -10192,16 +10191,16 @@ }, { "name": "laravel/pint", - "version": "v1.29.1", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80" + "reference": "72a0540d1aa10b6c146bda2a22f3ae003123c0ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/0770e9b7fafd50d4586881d456d6eb41c9247a80", - "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80", + "url": "https://api.github.com/repos/laravel/pint/zipball/72a0540d1aa10b6c146bda2a22f3ae003123c0ea", + "reference": "72a0540d1aa10b6c146bda2a22f3ae003123c0ea", "shasum": "" }, "require": { @@ -10212,14 +10211,16 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.95.1", - "illuminate/view": "^12.56.0", - "larastan/larastan": "^3.9.6", + "composer/semver": "^3.4.4", + "friendsofphp/php-cs-fixer": "^3.95.17", + "illuminate/view": "^12.64.0", + "larastan/larastan": "^3.10.0", "laravel-zero/framework": "^12.1.0", + "laravel/agent-detector": "^2.0.2", + "laravel/prompts": "^0.3.21", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^2.4.0", - "pestphp/pest": "^3.8.6", - "shipfastlabs/agent-detector": "^1.1.3" + "pestphp/pest": "^3.8.7" }, "bin": [ "builds/pint" @@ -10256,7 +10257,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2026-04-20T15:26:14+00:00" + "time": "2026-07-28T20:48:56+00:00" }, { "name": "laravel/roster", @@ -10464,23 +10465,23 @@ }, { "name": "nunomaduro/collision", - "version": "v8.9.4", + "version": "v8.9.5", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "716af8f95a470e9094cfca09ed897b023be191a5" + "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/716af8f95a470e9094cfca09ed897b023be191a5", - "reference": "716af8f95a470e9094cfca09ed897b023be191a5", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/fb53eacd509a1d303858e2d20cfebf2d630254ec", + "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec", "shasum": "" }, "require": { "filp/whoops": "^2.18.4", "nunomaduro/termwind": "^2.4.0", "php": "^8.2.0", - "symfony/console": "^7.4.8 || ^8.0.8" + "symfony/console": "^7.4.14 || ^8.1.1" }, "conflict": { "laravel/framework": "<11.48.0 || >=14.0.0", @@ -10488,12 +10489,12 @@ }, "require-dev": { "brianium/paratest": "^7.8.5", - "larastan/larastan": "^3.9.6", - "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.5.0", - "laravel/pint": "^1.29.1", - "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.2.1", - "pestphp/pest": "^3.8.5 || ^4.4.3 || ^5.0.0", - "sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.3.0" + "larastan/larastan": "^3.10.0", + "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.20.0", + "laravel/pint": "^1.29.3", + "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.3.5", + "pestphp/pest": "^3.8.5 || ^4.7.5 || ^5.0.0", + "sebastian/environment": "^7.2.1 || ^8.1.2 || ^9.3.2" }, "type": "library", "extra": { @@ -10556,20 +10557,20 @@ "type": "patreon" } ], - "time": "2026-04-21T14:04:20+00:00" + "time": "2026-07-15T19:09:14+00:00" }, { "name": "pestphp/pest", - "version": "v4.7.2", + "version": "v4.7.5", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "40b88b62ef8a7c6fcae5fc28f1fa747f601c131b" + "reference": "5dc49a71d63602a9b98fed0f2017c4679ef9f8e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/40b88b62ef8a7c6fcae5fc28f1fa747f601c131b", - "reference": "40b88b62ef8a7c6fcae5fc28f1fa747f601c131b", + "url": "https://api.github.com/repos/pestphp/pest/zipball/5dc49a71d63602a9b98fed0f2017c4679ef9f8e0", + "reference": "5dc49a71d63602a9b98fed0f2017c4679ef9f8e0", "shasum": "" }, "require": { @@ -10582,21 +10583,21 @@ "pestphp/pest-plugin-mutate": "^4.0.1", "pestphp/pest-plugin-profanity": "^4.2.1", "php": "^8.3.0", - "phpunit/phpunit": "^12.5.28", + "phpunit/phpunit": "^12.5.30", "symfony/process": "^7.4.13|^8.1.0" }, "conflict": { "filp/whoops": "<2.18.3", - "phpunit/phpunit": ">12.5.28", + "phpunit/phpunit": ">12.5.30", "sebastian/exporter": "<7.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { - "mrpunyapal/peststan": "^0.2.10", + "mrpunyapal/peststan": "^0.2.11", "pestphp/pest-dev-tools": "^4.1.0", "pestphp/pest-plugin-browser": "^4.3.1", "pestphp/pest-plugin-type-coverage": "^4.0.4", - "psy/psysh": "^0.12.23" + "psy/psysh": "^0.12.24" }, "bin": [ "bin/pest" @@ -10663,7 +10664,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v4.7.2" + "source": "https://github.com/pestphp/pest/tree/v4.7.5" }, "funding": [ { @@ -10675,7 +10676,7 @@ "type": "github" } ], - "time": "2026-06-01T06:08:59+00:00" + "time": "2026-07-06T17:06:29+00:00" }, { "name": "pestphp/pest-plugin", @@ -11143,16 +11144,16 @@ }, { "name": "php-debugbar/php-debugbar", - "version": "v3.7.6", + "version": "v3.8.0", "source": { "type": "git", "url": "https://github.com/php-debugbar/php-debugbar.git", - "reference": "1690ee1728827f9deb4b60457fa387cf44672c56" + "reference": "18ced90d4b882ed449b2278fea8692f8f7d1c13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/1690ee1728827f9deb4b60457fa387cf44672c56", - "reference": "1690ee1728827f9deb4b60457fa387cf44672c56", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/18ced90d4b882ed449b2278fea8692f8f7d1c13c", + "reference": "18ced90d4b882ed449b2278fea8692f8f7d1c13c", "shasum": "" }, "require": { @@ -11194,7 +11195,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.8-dev" } }, "autoload": { @@ -11229,7 +11230,7 @@ ], "support": { "issues": "https://github.com/php-debugbar/php-debugbar/issues", - "source": "https://github.com/php-debugbar/php-debugbar/tree/v3.7.6" + "source": "https://github.com/php-debugbar/php-debugbar/tree/v3.8.0" }, "funding": [ { @@ -11241,7 +11242,7 @@ "type": "github" } ], - "time": "2026-04-30T07:31:44+00:00" + "time": "2026-07-02T12:38:20+00:00" }, { "name": "php-debugbar/symfony-bridge", @@ -11487,16 +11488,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "shasum": "" }, "require": { @@ -11528,9 +11529,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" }, - "time": "2026-01-25T14:56:51+00:00" + "time": "2026-07-08T07:01:06+00:00" }, { "name": "phpunit/php-code-coverage", @@ -11879,16 +11880,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.28", + "version": "12.5.30", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5895d05f5bf421ed230fbd76e1277e4b8955def4" + "reference": "900400a5b616d6fb306f9549f6da33ba615d3fbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5895d05f5bf421ed230fbd76e1277e4b8955def4", - "reference": "5895d05f5bf421ed230fbd76e1277e4b8955def4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/900400a5b616d6fb306f9549f6da33ba615d3fbb", + "reference": "900400a5b616d6fb306f9549f6da33ba615d3fbb", "shasum": "" }, "require": { @@ -11902,7 +11903,7 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.6", + "phpunit/php-code-coverage": "^12.5.7", "phpunit/php-file-iterator": "^6.0.1", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", @@ -11912,7 +11913,7 @@ "sebastian/diff": "^7.0.0", "sebastian/environment": "^8.1.2", "sebastian/exporter": "^7.0.3", - "sebastian/global-state": "^8.0.2", + "sebastian/global-state": "^8.0.3", "sebastian/object-enumerator": "^7.0.0", "sebastian/recursion-context": "^7.0.1", "sebastian/type": "^6.0.4", @@ -11957,7 +11958,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.28" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.30" }, "funding": [ { @@ -11965,7 +11966,7 @@ "type": "other" } ], - "time": "2026-05-27T14:01:10+00:00" + "time": "2026-06-15T13:12:30+00:00" }, { "name": "sebastian/cli-parser", @@ -12930,16 +12931,16 @@ }, { "name": "symfony/yaml", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "efb42bd2c6f4f3ccfd4683583449938b5fc146b0" + "reference": "faabdbe998e8c5c599dceffa27aa265b185c0736" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/efb42bd2c6f4f3ccfd4683583449938b5fc146b0", - "reference": "efb42bd2c6f4f3ccfd4683583449938b5fc146b0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/faabdbe998e8c5c599dceffa27aa265b185c0736", + "reference": "faabdbe998e8c5c599dceffa27aa265b185c0736", "shasum": "" }, "require": { @@ -12982,7 +12983,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v8.1.0" + "source": "https://github.com/symfony/yaml/tree/v8.1.2" }, "funding": [ { @@ -13002,7 +13003,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", diff --git a/database/migrations/2026_05_01_172941_create_system_settings_table.php b/database/migrations/2026_05_01_172941_create_system_settings_table.php index 872d870..dec9650 100644 --- a/database/migrations/2026_05_01_172941_create_system_settings_table.php +++ b/database/migrations/2026_05_01_172941_create_system_settings_table.php @@ -15,6 +15,7 @@ return new class extends Migration $table->id(); $table->string('key')->unique(); $table->text('value')->nullable(); + $table->text('type'); }); } diff --git a/database/migrations/2026_07_06_031003_create_clients_table.php b/database/migrations/2026_07_06_031003_create_clients_table.php index b13507e..01a3976 100644 --- a/database/migrations/2026_07_06_031003_create_clients_table.php +++ b/database/migrations/2026_07_06_031003_create_clients_table.php @@ -15,9 +15,11 @@ return new class extends Migration $table->id(); $table->ulid(); $table->string('name'); - $table->string('url')->nullable(); - $table->string('code')->nullable(); - $table->string('secret'); + $table->string('domain'); + $table->text('secret'); + $table->text('auth_type'); + $table->text('webhook'); + $table->longText('credentials'); $table->timestamps(); }); } diff --git a/database/migrations/2026_07_31_035159_create_api_endpoints_table.php b/database/migrations/2026_07_31_035159_create_api_endpoints_table.php new file mode 100644 index 0000000..0778077 --- /dev/null +++ b/database/migrations/2026_07_31_035159_create_api_endpoints_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('key')->unique(); + $table->string('value'); + $table->foreignId('client_id')->constrained(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('api_endpoints'); + } +}; diff --git a/database/seeders/SystemSettingSeeder.php b/database/seeders/SystemSettingSeeder.php index 4a999c9..cab1793 100644 --- a/database/seeders/SystemSettingSeeder.php +++ b/database/seeders/SystemSettingSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Domains\Channel\Enums\Api\ApiType; use App\Domains\System\Enums\SystemSettingKey; use App\Domains\System\Models\SystemSettings; use Illuminate\Database\Seeder; @@ -18,6 +19,15 @@ class SystemSettingSeeder extends Seeder SystemSettings::create([ 'key' => $setting->value, 'value' => $setting->default(), + 'type' => SystemSettingKey::class, + ]); + } + + foreach (ApiType::cases() as $sync) { + SystemSettings::create([ + 'key' => $sync->value, + 'value' => '-', + 'type' => ApiType::class, ]); } } diff --git a/lang/en/domains/academic/field.php b/lang/en/domains/academic/field.php index 02bb44a..424f6e4 100644 --- a/lang/en/domains/academic/field.php +++ b/lang/en/domains/academic/field.php @@ -6,7 +6,7 @@ return [ 'code' => 'Faculty Code', 'status' => 'Status', ], - 'study-program' => [ + 'study_program' => [ 'name' => 'Study Program Name', 'code' => 'Study Program Code', 'status' => 'Status', diff --git a/lang/en/domains/academic/seo.php b/lang/en/domains/academic/seo.php index 327c86f..109fa01 100644 --- a/lang/en/domains/academic/seo.php +++ b/lang/en/domains/academic/seo.php @@ -6,7 +6,7 @@ return [ 'description' => 'Manage faculty data in the system.', 'keywords' => 'faculty, academic, university', ], - 'study-program' => [ + 'study_program' => [ 'title' => 'Study Program Data', 'description' => 'Manage study program data in the system.', 'keywords' => 'study program, academic, university', diff --git a/lang/en/domains/account/enum.php b/lang/en/domains/account/enum.php index 26c5ede..244282d 100644 --- a/lang/en/domains/account/enum.php +++ b/lang/en/domains/account/enum.php @@ -3,11 +3,11 @@ use App\Domains\Account\Enums\GenderOption; return [ - 'gender-option' => [ + 'gender_option' => [ GenderOption::MALE->value => 'Male', GenderOption::FEMALE->value => 'Female', ], - 'user_settings' => [ + 'user_setting_key' => [ 'notification' => 'Notification', 'language' => 'Language', 'timezone' => 'Timezone', diff --git a/lang/en/domains/admission/enum.php b/lang/en/domains/admission/enum.php index e103261..f05fdaf 100644 --- a/lang/en/domains/admission/enum.php +++ b/lang/en/domains/admission/enum.php @@ -1,15 +1,18 @@ [ - 'published' => 'Published', - 'draft' => 'Draft', - 'archived' => 'Archived', + 'admission_status' => [ + AdmissionStatus::PUBLISHED->value => 'Published', + AdmissionStatus::DRAFT->value => 'Draft', + AdmissionStatus::ARCHIVED->value => 'Archived', ], - 'billing-cycle' => [ - 'once' => 'Once', - 'monthly' => 'Monthly', - 'semester' => 'Semester', - 'annual' => 'Annual', + 'billing_cycle' => [ + BillingCycle::ONCE->value => 'Once', + BillingCycle::MONTHLY->value => 'Monthly', + BillingCycle::SEMESTER->value => 'Semester', + BillingCycle::ANNUAL->value => 'Annual', ], ]; diff --git a/lang/en/domains/admission/field.php b/lang/en/domains/admission/field.php index 52541a8..6efcbff 100644 --- a/lang/en/domains/admission/field.php +++ b/lang/en/domains/admission/field.php @@ -1,27 +1,31 @@ [ - 'date-start' => 'Start Date', - 'date-end' => 'End Date', - 're-registration-date-start' => 'Re-registration Start Date', - 're-registration-date-end' => 'Re-registration End Date', + 'admission_schedule' => [ + 'date_start' => 'Start Date', + 'date_end' => 'End Date', + 're_registration_date_start' => 'Re-registration Start Date', + 're_registration_date_end' => 'Re-registration End Date', 'track_name' => 'Track Name', 'status' => 'Status', 'term_name' => 'Term', ], - 'admission-track' => [ + 'admission_track' => [ 'code' => 'Track Code', 'name' => 'Admission Track Name', 'status' => 'Status', ], - 'fee-type' => [ + 'fee_type' => [ 'name' => 'Fee Type Name', 'billing_cycle' => 'Billing Cycle', ], - 'academic-program' => [ + 'academic_program' => [ 'code' => 'Academic Program Code', 'name' => 'Academic Program Name', 'status' => 'Status', ], + 'admission_schedule_detail' => [ + 'schedule_detail' => 'Admission Schedule Detail', + 'fee_detail' => 'Fee Detail', + ], ]; diff --git a/lang/en/domains/admission/seo.php b/lang/en/domains/admission/seo.php index eba5118..ec20dea 100644 --- a/lang/en/domains/admission/seo.php +++ b/lang/en/domains/admission/seo.php @@ -1,27 +1,27 @@ [ + 'admission_schedule' => [ 'title' => 'Admission Schedule Data', 'description' => 'Manage new student admission schedules.', 'keywords' => 'admission schedule, admission, new student', ], - 'admission-schedule-detail' => [ + 'admission_schedule_detail' => [ 'title' => 'Admission Schedule Detail', 'description' => 'View details of the admission schedule.', 'keywords' => 'admission schedule detail, admission, schedule', ], - 'admission-track' => [ + 'admission_track' => [ 'title' => 'Admission Track Data', 'description' => 'Manage new student admission tracks.', 'keywords' => 'admission track, admission, new student', ], - 'fee-type' => [ + 'fee_type' => [ 'title' => 'Fee Type Data', 'description' => 'Manage admission fee types.', 'keywords' => 'fee type, fee, admission', ], - 'academic-program' => [ + 'academic_program' => [ 'title' => 'Academic Program Data', 'description' => 'Manage admission academic programs.', 'keywords' => 'academic program, program, admission', diff --git a/lang/en/domains/channel/enum.php b/lang/en/domains/channel/enum.php new file mode 100644 index 0000000..e629305 --- /dev/null +++ b/lang/en/domains/channel/enum.php @@ -0,0 +1,21 @@ + [ + ApiType::FACULTY->value => 'Faculty', + ApiType::STUDY_PROGRAM->value => 'Study Program', + ApiType::TERM->value => 'Term', + ApiType::ADMISSION_TRACK->value => 'Admission Track', + ApiType::ADMISSION_SCHEDULE->value => 'Admission Schedule', + ApiType::ACADEMIC_PROGRAM->value => 'Academic Program', + ApiType::FEE_TYPE->value => 'Fee Type', + ], + 'auth_type' => [ + AuthType::NONE->value => 'None', + AuthType::BASIC->value => 'Basic', + AuthType::TOKEN->value => 'Token', + ], +]; diff --git a/lang/en/domains/channel/field.php b/lang/en/domains/channel/field.php index 2297c98..feda43a 100644 --- a/lang/en/domains/channel/field.php +++ b/lang/en/domains/channel/field.php @@ -3,7 +3,13 @@ return [ 'client' => [ 'name' => 'Client Name', - 'code' => 'Client Code', - 'url' => 'Integration URL', + 'domain' => 'Domain', + 'webhook' => 'Webhook URL', + 'auth_type' => 'Authentication Type', + 'credentials' => [ + 'username' => 'Username', + 'password' => 'Password', + 'token' => 'Token', + ], ], ]; diff --git a/lang/en/domains/finance/enum.php b/lang/en/domains/finance/enum.php index 58329d0..4cbfdec 100644 --- a/lang/en/domains/finance/enum.php +++ b/lang/en/domains/finance/enum.php @@ -1,32 +1,38 @@ [ - 'paid' => 'Paid', - 'pending' => 'Pending', - 'partially_paid' => 'Partially Paid', - 'overdue' => 'Overdue', + 'invoice_status' => [ + InvoiceStatus::PAID->value => 'Paid', + InvoiceStatus::PENDING->value => 'Pending', + InvoiceStatus::PARTIALLY_PAID->value => 'Partially Paid', + InvoiceStatus::OVERDUE->value => 'Overdue', ], - 'invoice-type' => [ - 'customer_invoice' => 'Customer Invoice', - 'vendor_bill' => 'Vendor Bill', - 'credit_note' => 'Credit Note', + 'invoice_type' => [ + InvoiceType::CUSTOMER_INVOICE->value => 'Customer Invoice', + InvoiceType::VENDOR_BILL->value => 'Vendor Bill', + InvoiceType::CREDIT_NOTE->value => 'Credit Note', ], - 'payment-status' => [ - 'pending' => 'Pending', - 'success' => 'Success', - 'failed' => 'Failed', - 'expired' => 'Expired', + 'payment_status' => [ + PaymentStatus::PENDING->value => 'Pending', + PaymentStatus::SUCCESS->value => 'Success', + PaymentStatus::FAILED->value => 'Failed', + PaymentStatus::EXPIRED->value => 'Expired', ], - 'payment-direction' => [ - 'receipt' => 'Receipt', - 'disbursement' => 'Disbursement', + 'payment_direction' => [ + PaymentDirection::RECEIPT->value => 'Receipt', + PaymentDirection::DISBURSEMENT->value => 'Disbursement', ], - 'account-classification' => [ - 'asset' => 'Asset', - 'liability' => 'Liability', - 'equity' => 'Equity', - 'revenue' => 'Revenue', - 'expense' => 'Expense', + 'account_classification' => [ + AccountClassification::ASSET->value => 'Asset', + AccountClassification::LIABILITY->value => 'Liability', + AccountClassification::EQUITY->value => 'Equity', + AccountClassification::REVENUE->value => 'Revenue', + AccountClassification::EXPENSE->value => 'Expense', ], ]; diff --git a/lang/en/domains/finance/seo.php b/lang/en/domains/finance/seo.php index d51aefd..08d3fd9 100644 --- a/lang/en/domains/finance/seo.php +++ b/lang/en/domains/finance/seo.php @@ -11,7 +11,7 @@ return [ 'description' => 'Manage student payment invoices.', 'keywords' => 'invoice, payment, finance', ], - 'product-mapping' => [ + 'product_mapping' => [ 'title' => 'Product Mapping Data', 'description' => 'Manage cost product mappings with Chart of Accounts (COA).', 'keywords' => 'product mapping, product, coa, finance', diff --git a/lang/en/domains/identity/enum.php b/lang/en/domains/identity/enum.php index f87b774..593740f 100644 --- a/lang/en/domains/identity/enum.php +++ b/lang/en/domains/identity/enum.php @@ -1,5 +1,6 @@ value => 'Active', UserStatus::INACTIVE->value => 'Inactive', ], + 'role_type' => [ + RoleType::SYSTEM_ADMIN->value => 'System Administrator', + RoleType::ADMIN->value => 'Administrator', + RoleType::USER->value => 'User', + ], + 'user_setting_key' => [ + 'notification' => 'Notification', + 'language' => 'Language', + 'timezone' => 'Timezone', + 'options' => [ + 'language' => [ + 'en' => 'English', + 'id' => 'Indonesian', + ], + 'notification' => [ + 'on' => 'On', + 'off' => 'Off', + ], + 'timezone' => [ + 'UTC' => 'UTC', + 'Asia/Jakarta' => 'Western Indonesia Time (Jakarta)', + 'Asia/Makassar' => 'Central Indonesia Time (Makassar)', + 'Asia/Jayapura' => 'Eastern Indonesia Time (Jayapura)', + ], + ], + ], ]; diff --git a/lang/en/domains/identity/messages.php b/lang/en/domains/identity/messages.php index 7871640..2095ee7 100644 --- a/lang/en/domains/identity/messages.php +++ b/lang/en/domains/identity/messages.php @@ -12,7 +12,7 @@ return [ 'failed_to_update_user_status' => 'Failed to update user status.', 'user_already_active' => 'This user is already active.', 'user_already_suspended' => 'This user is already suspended.', - 'user_already_in_status' => 'User is already :status.', + 'user_already_status' => 'User is already in this status.', 'user_cannot_be_edited' => 'This user can\'t be edited.', 'user_cannot_be_purged' => 'You can\'t purge an admin user.', 'user_cannot_be_suspended' => 'You can\'t suspend an admin user.', diff --git a/lang/en/domains/system/enum.php b/lang/en/domains/system/enum.php index 4ef4ff3..9104663 100644 --- a/lang/en/domains/system/enum.php +++ b/lang/en/domains/system/enum.php @@ -1,8 +1,36 @@ [ - 'active' => 'Active', - 'archived' => 'Archived', + 'lifecycle_status' => [ + LifecycleStatus::ACTIVE->value => 'Active', + LifecycleStatus::INACTIVE->value => 'Inactive', + ], + 'system_setting_key' => [ + SystemSettingKey::WEB_NAME->value => 'Website Name', + SystemSettingKey::WEB_DESCRIPTION->value => 'Website Description', + SystemSettingKey::WEB_LOGO->value => 'Website Logo', + SystemSettingKey::WEB_FAVICON->value => 'Website Favicon', + SystemSettingKey::WEB_PHONE->value => 'Website Phone', + SystemSettingKey::WEB_EMAIL->value => 'Website Email', + SystemSettingKey::WEB_ADDRESS->value => 'Website Address', + SystemSettingKey::DEFAULT_LANGUAGE->value => 'Default Language', + SystemSettingKey::TIMEZONE->value => 'Timezone', + SystemSettingKey::GOOGLE_TAG_MANAGER_ID->value => 'Google Tag Manager ID', + SystemSettingKey::GOOGLE_WEBMASTER_ID->value => 'Google Webmaster ID', + ], + 'system_setting_key_options' => [ + 'default_language' => [ + 'en' => 'English', + 'id' => 'Indonesian', + ], + 'timezone' => [ + 'UTC' => 'UTC', + 'Asia/Jakarta' => 'Western Indonesia Time (Jakarta)', + 'Asia/Makassar' => 'Central Indonesia Time (Makassar)', + 'Asia/Jayapura' => 'Eastern Indonesia Time (Jayapura)', + ], ], ]; diff --git a/lang/en/domains/system/pages.php b/lang/en/domains/system/pages.php index 30dbcf5..3fb7ec8 100644 --- a/lang/en/domains/system/pages.php +++ b/lang/en/domains/system/pages.php @@ -19,4 +19,10 @@ return [ 'webmaster' => 'Webmaster', ], ], + 'api' => [ + 'sections' => [ + 'academic' => 'Academic', + 'admission' => 'Admission', + ], + ], ]; diff --git a/lang/en/resources.php b/lang/en/resources.php index 4200688..3038e71 100644 --- a/lang/en/resources.php +++ b/lang/en/resources.php @@ -7,16 +7,19 @@ return [ 'settings' => 'Settings', 'password' => 'Password', 'backup' => 'Backup', - 'backup_file' => 'Backup File', 'avatar' => 'Avatar', 'system_settings' => 'System Settings', - 'audit' => 'Audit', + 'client' => 'Client', + 'faculty' => 'Faculty', 'study_program' => 'Study Program', 'admission_schedule' => 'Admission Schedule', 'admission_track' => 'Admission Track', - 'fee_type' => 'Fee Type', 'academic_program' => 'Academic Program', - 'client' => 'Client', - 'faculty' => 'Faculty', + 'fee_type' => 'Fee Type', 'term' => 'Term', + 'chart_of_account' => 'Chart of Account', + 'product_mapping' => 'Product Mapping', + 'backup_file' => 'Backup File', + 'invoice' => 'Invoice', + 'client-api' => 'Synchronization API Endpoint', ]; diff --git a/lang/en/ui.php b/lang/en/ui.php deleted file mode 100644 index 3bcb191..0000000 --- a/lang/en/ui.php +++ /dev/null @@ -1,107 +0,0 @@ - [ - 'dashboard' => 'Dashboard', - 'identity' => 'User Management', - 'users' => 'Users', - 'roles' => 'Roles & Permissions', - 'settings' => 'System Settings', - 'system_backup' => 'System Backup', - 'academic' => 'Academic', - 'faculties' => 'Faculties', - 'study-programs' => 'Study Programs', - 'terms' => 'Terms', - 'admission' => 'Admission', - 'admission-tracks' => 'Admission Tracks', - 'academic-programs' => 'Academic Programs', - 'fee-types' => 'Fee Types', - 'admission-schedules' => 'Admission Schedules', - 'finance' => 'Finance', - 'invoices' => 'Invoices', - 'chart-of-accounts' => 'Chart of Accounts', - 'product-mappings' => 'Product Mappings', - 'management' => 'Management', - 'profile' => 'Profile', - ], - 'title' => [ - 'index' => ':resource Data', - 'create' => 'Create New :resource', - 'update' => 'Update :resource', - 'delete' => 'Delete :resource', - 'view' => 'View :resource', - 'upload' => 'Upload :resource', - 'restore' => 'Restore :resource', - 'import' => 'Import :resource', - ], - 'greetings' => [ - 'morning' => 'Good morning, :name', - 'welcome' => 'Welcome back to the dashboard', - ], - 'label' => [ - 'id' => 'ID', - 'actions' => 'Actions', - 'created_at' => 'Created At', - 'updated_at' => 'Updated At', - 'status' => 'Status', - 'no_data' => 'No Data', - ], - 'button' => [ - 'save' => 'Save Changes', - 'cancel' => 'Cancel', - 'back' => 'Back', - 'close' => 'Close', - 'create' => 'Create', - 'update' => 'Update', - 'upload' => 'Upload', - 'edit' => 'Edit', - 'delete' => 'Delete', - 'suspend' => 'Suspend', - 'view' => 'View', - 'log' => 'Log', - 'yes' => 'Yes', - 'no' => 'No', - 'lookup' => 'Search...', - 'logout' => 'Logout', - ], - 'confirmation' => [ - 'logout' => 'Are you sure you want to logout?', - 'delete' => 'Are you sure you want to delete this :resource? This action cannot be undone.', - 'suspend' => 'Are you sure you want to suspend this :resource?', - ], - 'crud' => [ - 'success' => [ - 'created' => ':resource has been created successfully.', - 'updated' => ':resource has been updated successfully.', - 'deleted' => ':resource has been removed.', - 'suspended' => ':resource has been suspended.', - 'uploaded' => ':resource has been uploaded successfully.', - ], - 'error' => [ - 'forbidden' => 'You do not have permission to perform this action.', - 'validation_failed' => 'The given data was invalid.', - 'generic' => 'Something went wrong. Please try again.', - ], - ], - 'loading' => 'Loading...', - 'errors' => [ - 'oops' => 'Oops… You just found an error page', - '404' => 'We are sorry but the page you are looking for was not found.', - '500' => 'We are sorry but our server encountered an internal error.', - 'take_me_home' => 'Take me home', - ], - 'notification' => [ - 'empty' => 'No notifications', - 'read_all' => 'Read all notifications', - 'unread' => 'unread messages', - ], - 'excel' => [ - 'import' => [ - 'file_label' => 'Excel File', - 'success' => 'Import queued. You will receive an email when it is complete.', - ], - 'export' => [ - 'success' => 'Export queued. You will receive an email with the file when it is ready.', - ], - ], -]; diff --git a/lang/en/ui/button.php b/lang/en/ui/button.php new file mode 100644 index 0000000..f2d3ff7 --- /dev/null +++ b/lang/en/ui/button.php @@ -0,0 +1,20 @@ + 'Save Changes', + 'cancel' => 'Cancel', + 'back' => 'Back', + 'close' => 'Close', + 'create' => 'Create', + 'update' => 'Update', + 'upload' => 'Upload', + 'edit' => 'Edit', + 'delete' => 'Delete', + 'suspend' => 'Suspend', + 'view' => 'View', + 'log' => 'Log', + 'yes' => 'Yes', + 'no' => 'No', + 'lookup' => 'Search...', + 'logout' => 'Logout', +]; diff --git a/lang/en/ui/common.php b/lang/en/ui/common.php new file mode 100644 index 0000000..66aa647 --- /dev/null +++ b/lang/en/ui/common.php @@ -0,0 +1,5 @@ + 'Loading...', +]; diff --git a/lang/en/ui/confirmation.php b/lang/en/ui/confirmation.php new file mode 100644 index 0000000..89913be --- /dev/null +++ b/lang/en/ui/confirmation.php @@ -0,0 +1,7 @@ + 'Are you sure you want to logout?', + 'delete' => 'Are you sure you want to delete this :resource? This action cannot be undone.', + 'suspend' => 'Are you sure you want to suspend this :resource?', +]; diff --git a/lang/en/ui/crud.php b/lang/en/ui/crud.php new file mode 100644 index 0000000..7ac2dcb --- /dev/null +++ b/lang/en/ui/crud.php @@ -0,0 +1,16 @@ + [ + 'created' => ':resource has been created successfully.', + 'updated' => ':resource has been updated successfully.', + 'deleted' => ':resource has been removed.', + 'suspended' => ':resource has been suspended.', + 'uploaded' => ':resource has been uploaded successfully.', + ], + 'error' => [ + 'forbidden' => 'You do not have permission to perform this action.', + 'validation_failed' => 'The given data was invalid.', + 'generic' => 'Something went wrong. Please try again.', + ], +]; diff --git a/lang/en/ui/enum.php b/lang/en/ui/enum.php new file mode 100644 index 0000000..8357bbd --- /dev/null +++ b/lang/en/ui/enum.php @@ -0,0 +1,17 @@ + [ + 'number' => 'Number', + 'text_line' => 'Text Line', + 'text_area' => 'Text Area', + 'select' => 'Select', + 'file' => 'File', + 'checkbox' => 'Checkbox', + ], + 'file_type' => [ + 'document' => 'Document', + 'image' => 'Image', + 'audio' => 'Audio', + ], +]; diff --git a/lang/en/ui/errors.php b/lang/en/ui/errors.php new file mode 100644 index 0000000..43cbdc0 --- /dev/null +++ b/lang/en/ui/errors.php @@ -0,0 +1,8 @@ + 'Oops… You just found an error page', + '404' => 'We are sorry but the page you are looking for was not found.', + '500' => 'We are sorry but our server encountered an internal error.', + 'take_me_home' => 'Take me home', +]; diff --git a/lang/en/ui/excel.php b/lang/en/ui/excel.php new file mode 100644 index 0000000..3b5a4b5 --- /dev/null +++ b/lang/en/ui/excel.php @@ -0,0 +1,11 @@ + [ + 'file_label' => 'Excel File', + 'success' => 'Import queued. You will receive an email when it is complete.', + ], + 'export' => [ + 'success' => 'Export queued. You will receive an email with the file when it is ready.', + ], +]; diff --git a/lang/en/ui/greetings.php b/lang/en/ui/greetings.php new file mode 100644 index 0000000..30edcf3 --- /dev/null +++ b/lang/en/ui/greetings.php @@ -0,0 +1,6 @@ + 'Good morning, :name', + 'welcome' => 'Welcome back to the dashboard', +]; diff --git a/lang/en/ui/label.php b/lang/en/ui/label.php new file mode 100644 index 0000000..2b8cdf6 --- /dev/null +++ b/lang/en/ui/label.php @@ -0,0 +1,11 @@ + 'ID', + 'actions' => 'Actions', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'status' => 'Status', + 'no_data' => 'No Data Available', + 'fee_type' => 'Fee Type', +]; diff --git a/lang/en/ui/menu.php b/lang/en/ui/menu.php new file mode 100644 index 0000000..4f39a6c --- /dev/null +++ b/lang/en/ui/menu.php @@ -0,0 +1,28 @@ + 'Dashboard', + 'profile' => 'Profile', + 'academic' => 'Academic', + 'faculties' => 'Faculties', + 'study_programs' => 'Study Programs', + 'terms' => 'Terms', + 'admission' => 'Admission', + 'admission_tracks' => 'Admission Tracks', + 'academic_programs' => 'Academic Programs', + 'fee_types' => 'Fee Types', + 'admission_schedules' => 'Admission Schedules', + 'channel' => 'Channel', + 'clients' => 'Clients', + 'finance' => 'Finance', + 'invoices' => 'Invoices', + 'chart_of_accounts' => 'Chart of Accounts', + 'product_mappings' => 'Product Mappings', + 'identity' => 'User Management', + 'users' => 'Users', + 'roles' => 'Roles & Permissions', + 'management' => 'Management', + 'settings' => 'System Settings', + 'system_backup' => 'System Backup', + 'api_callback' => 'API Callback', +]; diff --git a/lang/en/ui/notification.php b/lang/en/ui/notification.php new file mode 100644 index 0000000..9e5014f --- /dev/null +++ b/lang/en/ui/notification.php @@ -0,0 +1,7 @@ + 'No notifications', + 'read_all' => 'Read all notifications', + 'unread' => 'unread messages', +]; diff --git a/lang/en/ui/title.php b/lang/en/ui/title.php new file mode 100644 index 0000000..5dddba4 --- /dev/null +++ b/lang/en/ui/title.php @@ -0,0 +1,12 @@ + ':resource Data', + 'create' => 'Create New :resource', + 'update' => 'Update :resource', + 'delete' => 'Delete :resource', + 'view' => 'View :resource', + 'upload' => 'Upload :resource', + 'restore' => 'Restore :resource', + 'import' => 'Import :resource', +]; diff --git a/lang/id/domains/academic/field.php b/lang/id/domains/academic/field.php index 2a28e37..4dde791 100644 --- a/lang/id/domains/academic/field.php +++ b/lang/id/domains/academic/field.php @@ -6,7 +6,7 @@ return [ 'code' => 'Kode Fakultas', 'status' => 'Status', ], - 'study-program' => [ + 'study_program' => [ 'name' => 'Nama Program Studi', 'code' => 'Kode Program Studi', 'status' => 'Status', diff --git a/lang/id/domains/academic/seo.php b/lang/id/domains/academic/seo.php index 695b516..e0e8013 100644 --- a/lang/id/domains/academic/seo.php +++ b/lang/id/domains/academic/seo.php @@ -6,7 +6,7 @@ return [ 'description' => 'Kelola data fakultas dalam sistem.', 'keywords' => 'fakultas, akademik, universitas', ], - 'study-program' => [ + 'study_program' => [ 'title' => 'Data Program Studi', 'description' => 'Kelola data program studi dalam sistem.', 'keywords' => 'program studi, akademik, universitas', diff --git a/lang/id/domains/account/enum.php b/lang/id/domains/account/enum.php index aed1d25..ae9aa34 100644 --- a/lang/id/domains/account/enum.php +++ b/lang/id/domains/account/enum.php @@ -3,11 +3,11 @@ use App\Domains\Account\Enums\GenderOption; return [ - 'gender-option' => [ + 'gender_option' => [ GenderOption::MALE->value => 'Laki-laki', GenderOption::FEMALE->value => 'Perempuan', ], - 'user_settings' => [ + 'user_setting_key' => [ 'notification' => 'Notifikasi', 'language' => 'Bahasa', 'timezone' => 'Zona Waktu', diff --git a/lang/id/domains/admission/enum.php b/lang/id/domains/admission/enum.php index dc88621..342dffb 100644 --- a/lang/id/domains/admission/enum.php +++ b/lang/id/domains/admission/enum.php @@ -1,15 +1,18 @@ [ - 'published' => 'Dipublikasikan', - 'draft' => 'Draf', - 'archived' => 'Diarsipkan', + 'admission_status' => [ + AdmissionStatus::PUBLISHED->value => 'Dipublikasikan', + AdmissionStatus::DRAFT->value => 'Draf', + AdmissionStatus::ARCHIVED->value => 'Diarsipkan', ], - 'billing-cycle' => [ - 'once' => 'Sekali', - 'monthly' => 'Bulanan', - 'semester' => 'Semester', - 'annual' => 'Tahunan', + 'billing_cycle' => [ + BillingCycle::ONCE->value => 'Sekali', + BillingCycle::MONTHLY->value => 'Bulanan', + BillingCycle::SEMESTER->value => 'Semester', + BillingCycle::ANNUAL->value => 'Tahunan', ], ]; diff --git a/lang/id/domains/admission/field.php b/lang/id/domains/admission/field.php index 78e4c9f..d87a5c1 100644 --- a/lang/id/domains/admission/field.php +++ b/lang/id/domains/admission/field.php @@ -1,27 +1,31 @@ [ - 'date-start' => 'Tanggal Mulai', - 'date-end' => 'Tanggal Selesai', - 're-registration-date-start' => 'Tanggal Mulai Daftar Ulang', - 're-registration-date-end' => 'Tanggal Selesai Daftar Ulang', + 'admission_schedule' => [ + 'date_start' => 'Tanggal Mulai', + 'date_end' => 'Tanggal Selesai', + 're_registration_date_start' => 'Tanggal Mulai Daftar Ulang', + 're_registration_date_end' => 'Tanggal Selesai Daftar Ulang', 'track_name' => 'Nama Jalur', 'status' => 'Status', 'term_name' => 'Tahun Ajaran', ], - 'admission-track' => [ + 'admission_track' => [ 'code' => 'Kode Jalur', 'name' => 'Nama Jalur Penerimaan', 'status' => 'Status', ], - 'fee-type' => [ + 'fee_type' => [ 'name' => 'Nama Jenis Biaya', 'billing_cycle' => 'Siklus Tagihan', ], - 'academic-program' => [ + 'academic_program' => [ 'code' => 'Kode Program Akademik', 'name' => 'Nama Program Akademik', 'status' => 'Status', ], + 'admission_schedule_detail' => [ + 'schedule_detail' => 'Detail Jadwal Penerimaan', + 'fee_detail' => 'Detail Biaya', + ], ]; diff --git a/lang/id/domains/admission/seo.php b/lang/id/domains/admission/seo.php index a701a61..ddd5c81 100644 --- a/lang/id/domains/admission/seo.php +++ b/lang/id/domains/admission/seo.php @@ -1,27 +1,27 @@ [ + 'admission_schedule' => [ 'title' => 'Data Jadwal Penerimaan', 'description' => 'Kelola jadwal penerimaan mahasiswa baru.', 'keywords' => 'jadwal penerimaan, penerimaan, mahasiswa baru', ], - 'admission-schedule-detail' => [ + 'admission_schedule_detail' => [ 'title' => 'Detail Jadwal Penerimaan', 'description' => 'Lihat detail jadwal penerimaan.', 'keywords' => 'detail jadwal penerimaan, penerimaan, jadwal', ], - 'admission-track' => [ + 'admission_track' => [ 'title' => 'Data Jalur Penerimaan', 'description' => 'Kelola jalur penerimaan mahasiswa baru.', 'keywords' => 'jalur penerimaan, penerimaan, mahasiswa baru', ], - 'fee-type' => [ + 'fee_type' => [ 'title' => 'Data Jenis Biaya', 'description' => 'Kelola jenis biaya penerimaan.', 'keywords' => 'jenis biaya, biaya, penerimaan', ], - 'academic-program' => [ + 'academic_program' => [ 'title' => 'Data Program Akademik', 'description' => 'Kelola program akademik penerimaan.', 'keywords' => 'program akademik, program, penerimaan', diff --git a/lang/id/domains/channel/enum.php b/lang/id/domains/channel/enum.php new file mode 100644 index 0000000..b30b022 --- /dev/null +++ b/lang/id/domains/channel/enum.php @@ -0,0 +1,21 @@ + [ + ApiType::FACULTY->value => 'Fakultas', + ApiType::STUDY_PROGRAM->value => 'Program Studi', + ApiType::TERM->value => 'Semester', + ApiType::ADMISSION_TRACK->value => 'Jalur Pendaftaran', + ApiType::ADMISSION_SCHEDULE->value => 'Jadwal Pendaftaran', + ApiType::ACADEMIC_PROGRAM->value => 'Program Akademik', + ApiType::FEE_TYPE->value => 'Jenis Biaya', + ], + 'auth_type' => [ + AuthType::NONE->value => 'Tidak Ada', + AuthType::BASIC->value => 'Dasar', + AuthType::TOKEN->value => 'Token', + ], +]; diff --git a/lang/id/domains/channel/field.php b/lang/id/domains/channel/field.php index 5c0af5f..c8de994 100644 --- a/lang/id/domains/channel/field.php +++ b/lang/id/domains/channel/field.php @@ -3,7 +3,13 @@ return [ 'client' => [ 'name' => 'Nama Klien', - 'code' => 'Kode Klien', - 'url' => 'URL Integrasi', + 'domain' => 'Domain', + 'webhook' => 'URL Webhook', + 'auth_type' => 'Tipe Autentikasi', + 'credentials' => [ + 'username' => 'Nama Pengguna', + 'password' => 'Password', + 'token' => 'Token', + ], ], ]; diff --git a/lang/id/domains/finance/enum.php b/lang/id/domains/finance/enum.php index 1f4a163..af8b78f 100644 --- a/lang/id/domains/finance/enum.php +++ b/lang/id/domains/finance/enum.php @@ -1,32 +1,38 @@ [ - 'paid' => 'Lunas', - 'pending' => 'Tertunda', - 'partially_paid' => 'Dibayar Sebagian', - 'overdue' => 'Jatuh Tempo', + 'invoice_status' => [ + InvoiceStatus::PAID->value => 'Lunas', + InvoiceStatus::PENDING->value => 'Tertunda', + InvoiceStatus::PARTIALLY_PAID->value => 'Dibayar Sebagian', + InvoiceStatus::OVERDUE->value => 'Jatuh Tempo', ], - 'invoice-type' => [ - 'customer_invoice' => 'Faktur Pelanggan', - 'vendor_bill' => 'Tagihan Vendor', - 'credit_note' => 'Nota Kredit', + 'invoice_type' => [ + InvoiceType::CUSTOMER_INVOICE->value => 'Faktur Pelanggan', + InvoiceType::VENDOR_BILL->value => 'Tagihan Vendor', + InvoiceType::CREDIT_NOTE->value => 'Nota Kredit', ], - 'payment-status' => [ - 'pending' => 'Tertunda', - 'success' => 'Berhasil', - 'failed' => 'Gagal', - 'expired' => 'Kedaluwarsa', + 'payment_status' => [ + PaymentStatus::PENDING->value => 'Tertunda', + PaymentStatus::SUCCESS->value => 'Berhasil', + PaymentStatus::FAILED->value => 'Gagal', + PaymentStatus::EXPIRED->value => 'Kedaluwarsa', ], - 'payment-direction' => [ - 'receipt' => 'Penerimaan', - 'disbursement' => 'Pengeluaran', + 'payment_direction' => [ + PaymentDirection::RECEIPT->value => 'Penerimaan', + PaymentDirection::DISBURSEMENT->value => 'Pengeluaran', ], - 'account-classification' => [ - 'asset' => 'Aset', - 'liability' => 'Kewajiban', - 'equity' => 'Ekuitas', - 'revenue' => 'Pendapatan', - 'expense' => 'Beban', + 'account_classification' => [ + AccountClassification::ASSET->value => 'Aset', + AccountClassification::LIABILITY->value => 'Kewajiban', + AccountClassification::EQUITY->value => 'Ekuitas', + AccountClassification::REVENUE->value => 'Pendapatan', + AccountClassification::EXPENSE->value => 'Beban', ], ]; diff --git a/lang/id/domains/finance/seo.php b/lang/id/domains/finance/seo.php index 44c6318..2a9613d 100644 --- a/lang/id/domains/finance/seo.php +++ b/lang/id/domains/finance/seo.php @@ -11,7 +11,7 @@ return [ 'description' => 'Kelola tagihan pembayaran mahasiswa.', 'keywords' => 'tagihan, invoice, pembayaran, keuangan', ], - 'product-mapping' => [ + 'product_mapping' => [ 'title' => 'Data Pemetaan Produk', 'description' => 'Kelola pemetaan produk biaya dengan Bagan Akun (COA).', 'keywords' => 'pemetaan produk, produk, coa, keuangan', diff --git a/lang/id/domains/identity/enum.php b/lang/id/domains/identity/enum.php index 5fc7ee8..35d3417 100644 --- a/lang/id/domains/identity/enum.php +++ b/lang/id/domains/identity/enum.php @@ -1,10 +1,37 @@ [ UserStatus::ACTIVE->value => 'Aktif', - UserStatus::INACTIVE->value => 'Non Aktif', + UserStatus::INACTIVE->value => 'Nonaktif', + ], + 'role_type' => [ + RoleType::SYSTEM_ADMIN->value => 'Administrator Sistem', + RoleType::ADMIN->value => 'Administrator', + RoleType::USER->value => 'Pengguna', + ], + 'user_setting_key' => [ + 'notification' => 'Notifikasi', + 'language' => 'Bahasa', + 'timezone' => 'Zona Waktu', + 'options' => [ + 'language' => [ + 'en' => 'Inggris', + 'id' => 'Indonesia', + ], + 'notification' => [ + 'on' => 'Aktif', + 'off' => 'Nonaktif', + ], + 'timezone' => [ + 'UTC' => 'UTC', + 'Asia/Jakarta' => 'Waktu Indonesia Barat (Jakarta)', + 'Asia/Makassar' => 'Waktu Indonesia Tengah (Makassar)', + 'Asia/Jayapura' => 'Waktu Indonesia Timur (Jayapura)', + ], + ], ], ]; diff --git a/lang/id/domains/identity/messages.php b/lang/id/domains/identity/messages.php index 845d1b9..9e49202 100644 --- a/lang/id/domains/identity/messages.php +++ b/lang/id/domains/identity/messages.php @@ -12,7 +12,7 @@ return [ 'failed_to_update_user_status' => 'Gagal memperbarui status pengguna.', 'user_already_active' => 'Pengguna ini sudah aktif.', 'user_already_suspended' => 'Pengguna ini sudah dinonaktifkan.', - 'user_already_in_status' => 'Pengguna sudah dalam status :status.', + 'user_already_status' => 'Pengguna sudah dalam status ini.', 'user_cannot_be_edited' => 'Pengguna ini tidak dapat diubah.', 'user_cannot_be_purged' => 'Anda tidak dapat menghapus admin.', 'user_cannot_be_suspended' => 'Anda tidak dapat menonaktifkan admin.', diff --git a/lang/id/domains/system/enum.php b/lang/id/domains/system/enum.php index 9da35f6..aa64ff6 100644 --- a/lang/id/domains/system/enum.php +++ b/lang/id/domains/system/enum.php @@ -1,8 +1,36 @@ [ - 'active' => 'Aktif', - 'archived' => 'Diarsipkan', + 'lifecycle_status' => [ + LifecycleStatus::ACTIVE->value => 'Aktif', + LifecycleStatus::INACTIVE->value => 'Tidak Aktif', + ], + 'system_setting_key' => [ + SystemSettingKey::WEB_NAME->value => 'Nama Situs Web', + SystemSettingKey::WEB_DESCRIPTION->value => 'Deskripsi Situs Web', + SystemSettingKey::WEB_LOGO->value => 'Logo Situs Web', + SystemSettingKey::WEB_FAVICON->value => 'Favicon Situs Web', + SystemSettingKey::WEB_PHONE->value => 'Telepon Situs Web', + SystemSettingKey::WEB_EMAIL->value => 'Email Situs Web', + SystemSettingKey::WEB_ADDRESS->value => 'Alamat Situs Web', + SystemSettingKey::DEFAULT_LANGUAGE->value => 'Bahasa Default', + SystemSettingKey::TIMEZONE->value => 'Zona Waktu', + SystemSettingKey::GOOGLE_TAG_MANAGER_ID->value => 'ID Google Tag Manager', + SystemSettingKey::GOOGLE_WEBMASTER_ID->value => 'ID Google Webmaster', + ], + 'system_setting_key_options' => [ + 'default_language' => [ + 'en' => 'Inggris', + 'id' => 'Indonesia', + ], + 'timezone' => [ + 'UTC' => 'UTC', + 'Asia/Jakarta' => 'Waktu Indonesia Barat (Jakarta)', + 'Asia/Makassar' => 'Waktu Indonesia Tengah (Makassar)', + 'Asia/Jayapura' => 'Waktu Indonesia Timur (Jayapura)', + ], ], ]; diff --git a/lang/id/domains/system/pages.php b/lang/id/domains/system/pages.php index f64440e..0423567 100644 --- a/lang/id/domains/system/pages.php +++ b/lang/id/domains/system/pages.php @@ -19,4 +19,10 @@ return [ 'webmaster' => 'Webmaster', ], ], + 'api' => [ + 'sections' => [ + 'academic' => 'Akademik', + 'admission' => 'Penerimaan', + ], + ], ]; diff --git a/lang/id/resources.php b/lang/id/resources.php index 33da898..28db34a 100644 --- a/lang/id/resources.php +++ b/lang/id/resources.php @@ -10,13 +10,16 @@ return [ 'backup_file' => 'Berkas Cadangan', 'avatar' => 'Avatar', 'system_settings' => 'Pengaturan Sistem', - 'audit' => 'Audit', + 'client' => 'Klien', + 'faculty' => 'Fakultas', 'study_program' => 'Program Studi', 'admission_schedule' => 'Jadwal Penerimaan', 'admission_track' => 'Jalur Penerimaan', - 'fee_type' => 'Jenis Biaya', 'academic_program' => 'Program Akademik', - 'client' => 'Klien', - 'faculty' => 'Fakultas', + 'fee_type' => 'Jenis Biaya', 'term' => 'Tahun Ajaran', + 'chart_of_account' => 'Bagan Akun', + 'product_mapping' => 'Pemetaan Produk', + 'invoice' => 'Tagihan', + 'client-api' => 'Titik Akhir Sinkronisasi API', ]; diff --git a/lang/id/ui.php b/lang/id/ui.php deleted file mode 100644 index 89e2f81..0000000 --- a/lang/id/ui.php +++ /dev/null @@ -1,107 +0,0 @@ - [ - 'dashboard' => 'Dasbor', - 'identity' => 'Manajemen Pengguna', - 'users' => 'Pengguna', - 'roles' => 'Peran & Izin', - 'settings' => 'Pengaturan Sistem', - 'system_backup' => 'Cadangkan Sistem', - 'academic' => 'Akademik', - 'faculties' => 'Fakultas', - 'study-programs' => 'Program Studi', - 'terms' => 'Tahun Ajaran', - 'admission' => 'Penerimaan', - 'admission-tracks' => 'Jalur Penerimaan', - 'academic-programs' => 'Program Akademik', - 'fee-types' => 'Jenis Biaya', - 'admission-schedules' => 'Jadwal Penerimaan', - 'finance' => 'Keuangan', - 'invoices' => 'Tagihan', - 'chart-of-accounts' => 'Bagan Akun', - 'product-mappings' => 'Pemetaan Produk', - 'management' => 'Manajemen', - 'profile' => 'Profil', - ], - 'title' => [ - 'index' => 'Data :resource', - 'create' => 'Buat :resource Baru', - 'update' => 'Perbarui :resource', - 'delete' => 'Hapus :resource', - 'view' => 'Lihat :resource', - 'upload' => 'Unggah :resource', - 'restore' => 'Pulihkan :resource', - 'import' => 'Impor :resource', - ], - 'greetings' => [ - 'morning' => 'Selamat pagi, :name', - 'welcome' => 'Selamat datang kembali di dasbor', - ], - 'label' => [ - 'id' => 'ID', - 'actions' => 'Aksi', - 'created_at' => 'Dibuat Pada', - 'updated_at' => 'Diperbarui Pada', - 'status' => 'Status', - 'no_data' => 'Tidak Ada Data', - ], - 'button' => [ - 'save' => 'Simpan Perubahan', - 'cancel' => 'Batal', - 'back' => 'Kembali', - 'close' => 'Tutup', - 'create' => 'Buat', - 'update' => 'Perbarui', - 'upload' => 'Unggah', - 'edit' => 'Ubah', - 'delete' => 'Hapus', - 'suspend' => 'Tangguhkan', - 'view' => 'Lihat', - 'log' => 'Log', - 'yes' => 'Ya', - 'no' => 'Tidak', - 'lookup' => 'Cari...', - 'logout' => 'Keluar', - ], - 'confirmation' => [ - 'logout' => 'Apakah Anda yakin ingin keluar?', - 'delete' => 'Apakah Anda yakin ingin menghapus :resource ini? Tindakan ini tidak dapat dibatalkan.', - 'suspend' => 'Apakah Anda yakin ingin menangguhkan :resource ini?', - ], - 'crud' => [ - 'success' => [ - 'created' => ':resource telah berhasil dibuat.', - 'updated' => ':resource telah berhasil diperbarui.', - 'deleted' => ':resource telah dihapus.', - 'suspended' => ':resource telah ditangguhkan.', - 'uploaded' => ':resource telah berhasil diunggah.', - ], - 'error' => [ - 'forbidden' => 'Anda tidak memiliki izin untuk melakukan tindakan ini.', - 'validation_failed' => 'Data yang diberikan tidak valid.', - 'generic' => 'Terjadi kesalahan. Silakan coba lagi.', - ], - ], - 'loading' => 'Memuat...', - 'errors' => [ - 'oops' => 'Ups... Terjadi kesalahan.', - '404' => 'Maaf, halaman yang Anda cari tidak ditemukan.', - '500' => 'Maaf, server kami sedang mengalami gangguan.', - 'take_me_home' => 'Kembali ke Beranda', - ], - 'notification' => [ - 'empty' => 'Tidak ada pemberitahuan', - 'read_all' => 'Baca semua pemberitahuan', - 'unread' => 'pesan belum dibaca', - ], - 'excel' => [ - 'import' => [ - 'file_label' => 'Berkas Excel', - 'success' => 'Impor dijadwalkan. Anda akan menerima email ketika selesai.', - ], - 'export' => [ - 'success' => 'Ekspor dijadwalkan. Anda akan menerima email beserta berkasnya ketika siap.', - ], - ], -]; diff --git a/lang/id/ui/button.php b/lang/id/ui/button.php new file mode 100644 index 0000000..8f7c96d --- /dev/null +++ b/lang/id/ui/button.php @@ -0,0 +1,20 @@ + 'Simpan Perubahan', + 'cancel' => 'Batal', + 'back' => 'Kembali', + 'close' => 'Tutup', + 'create' => 'Buat', + 'update' => 'Perbarui', + 'upload' => 'Unggah', + 'edit' => 'Ubah', + 'delete' => 'Hapus', + 'suspend' => 'Tangguhkan', + 'view' => 'Lihat', + 'log' => 'Log', + 'yes' => 'Ya', + 'no' => 'Tidak', + 'lookup' => 'Cari...', + 'logout' => 'Keluar', +]; diff --git a/lang/id/ui/common.php b/lang/id/ui/common.php new file mode 100644 index 0000000..940c088 --- /dev/null +++ b/lang/id/ui/common.php @@ -0,0 +1,5 @@ + 'Memuat...', +]; diff --git a/lang/id/ui/confirmation.php b/lang/id/ui/confirmation.php new file mode 100644 index 0000000..d32709d --- /dev/null +++ b/lang/id/ui/confirmation.php @@ -0,0 +1,7 @@ + 'Apakah Anda yakin ingin keluar?', + 'delete' => 'Apakah Anda yakin ingin menghapus :resource ini? Tindakan ini tidak dapat dibatalkan.', + 'suspend' => 'Apakah Anda yakin ingin menangguhkan :resource ini?', +]; diff --git a/lang/id/ui/crud.php b/lang/id/ui/crud.php new file mode 100644 index 0000000..4584f06 --- /dev/null +++ b/lang/id/ui/crud.php @@ -0,0 +1,16 @@ + [ + 'created' => ':resource telah berhasil dibuat.', + 'updated' => ':resource telah berhasil diperbarui.', + 'deleted' => ':resource telah dihapus.', + 'suspended' => ':resource telah ditangguhkan.', + 'uploaded' => ':resource telah berhasil diunggah.', + ], + 'error' => [ + 'forbidden' => 'Anda tidak memiliki izin untuk melakukan tindakan ini.', + 'validation_failed' => 'Data yang diberikan tidak valid.', + 'generic' => 'Terjadi kesalahan. Silakan coba lagi.', + ], +]; diff --git a/lang/id/ui/enum.php b/lang/id/ui/enum.php new file mode 100644 index 0000000..e40f778 --- /dev/null +++ b/lang/id/ui/enum.php @@ -0,0 +1,17 @@ + [ + 'number' => 'Angka', + 'text_line' => 'Baris Teks', + 'text_area' => 'Area Teks', + 'select' => 'Pilih', + 'file' => 'Berkas', + 'checkbox' => 'Kotak Centang', + ], + 'file_type' => [ + 'document' => 'Dokumen', + 'image' => 'Gambar', + 'audio' => 'Audio', + ], +]; diff --git a/lang/id/ui/errors.php b/lang/id/ui/errors.php new file mode 100644 index 0000000..deac8af --- /dev/null +++ b/lang/id/ui/errors.php @@ -0,0 +1,8 @@ + 'Ups... Terjadi kesalahan.', + '404' => 'Maaf, halaman yang Anda cari tidak ditemukan.', + '500' => 'Maaf, server kami sedang mengalami gangguan.', + 'take_me_home' => 'Kembali ke Beranda', +]; diff --git a/lang/id/ui/excel.php b/lang/id/ui/excel.php new file mode 100644 index 0000000..9ed42ed --- /dev/null +++ b/lang/id/ui/excel.php @@ -0,0 +1,11 @@ + [ + 'file_label' => 'Berkas Excel', + 'success' => 'Impor dijadwalkan. Anda akan menerima email ketika selesai.', + ], + 'export' => [ + 'success' => 'Ekspor dijadwalkan. Anda akan menerima email beserta berkasnya ketika siap.', + ], +]; diff --git a/lang/id/ui/greetings.php b/lang/id/ui/greetings.php new file mode 100644 index 0000000..cd29d57 --- /dev/null +++ b/lang/id/ui/greetings.php @@ -0,0 +1,6 @@ + 'Selamat pagi, :name', + 'welcome' => 'Selamat datang kembali di dasbor', +]; diff --git a/lang/id/ui/label.php b/lang/id/ui/label.php new file mode 100644 index 0000000..8f2afa9 --- /dev/null +++ b/lang/id/ui/label.php @@ -0,0 +1,11 @@ + 'ID', + 'actions' => 'Aksi', + 'created_at' => 'Dibuat Pada', + 'updated_at' => 'Diperbarui Pada', + 'status' => 'Status', + 'no_data' => 'Tidak Ada Data', + 'fee_type' => 'Jenis Biaya', +]; diff --git a/lang/id/ui/menu.php b/lang/id/ui/menu.php new file mode 100644 index 0000000..9168c74 --- /dev/null +++ b/lang/id/ui/menu.php @@ -0,0 +1,28 @@ + 'Dasbor', + 'profile' => 'Profil', + 'academic' => 'Akademik', + 'faculties' => 'Fakultas', + 'study_programs' => 'Program Studi', + 'terms' => 'Semester', + 'admission' => 'Penerimaan', + 'admission_tracks' => 'Jalur Penerimaan', + 'academic_programs' => 'Program Akademik', + 'fee_types' => 'Jenis Biaya', + 'admission_schedules' => 'Jadwal Penerimaan', + 'channel' => 'Saluran', + 'clients' => 'Klien', + 'finance' => 'Keuangan', + 'invoices' => 'Tagihan', + 'chart_of_accounts' => 'Bagan Akun', + 'product_mappings' => 'Pemetaan Produk', + 'identity' => 'Manajemen Pengguna', + 'users' => 'Pengguna', + 'roles' => 'Peran & Izin', + 'management' => 'Manajemen', + 'settings' => 'Pengaturan Sistem', + 'system_backup' => 'Cadangkan Sistem', + 'api_callback' => 'Callback API', +]; diff --git a/lang/id/ui/notification.php b/lang/id/ui/notification.php new file mode 100644 index 0000000..c17b5b4 --- /dev/null +++ b/lang/id/ui/notification.php @@ -0,0 +1,7 @@ + 'Tidak ada pemberitahuan', + 'read_all' => 'Baca semua pemberitahuan', + 'unread' => 'pesan belum dibaca', +]; diff --git a/lang/id/ui/title.php b/lang/id/ui/title.php new file mode 100644 index 0000000..f5500a5 --- /dev/null +++ b/lang/id/ui/title.php @@ -0,0 +1,12 @@ + 'Data :resource', + 'create' => 'Buat :resource Baru', + 'update' => 'Perbarui :resource', + 'delete' => 'Hapus :resource', + 'view' => 'Lihat :resource', + 'upload' => 'Unggah :resource', + 'restore' => 'Pulihkan :resource', + 'import' => 'Impor :resource', +]; diff --git a/package-lock.json b/package-lock.json index b3b0ed7..238b21a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,9 @@ "concurrently": "^9.0.1", "laravel-vite-plugin": "^3.0.0", "postcss": "8.5.10", + "prettier": "^3.9.6", + "prettier-plugin-blade": "^3.2.2", + "prettier-plugin-tailwindcss": "^0.8.1", "sass": "^1.99.0", "sweetalert2": "^11.26.24", "vite": "^8.0.7" @@ -439,6 +442,20 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@prettier/html-tags": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@prettier/html-tags/-/html-tags-2.2.0.tgz", + "integrity": "sha512-6qLjt8ncestmSfEOeVf/kX5VhkinUsppybvkwn1X7wu+BjQ/GBSZYu7cytxdCvi5BaljCGIAr4rmfL5zVqdgyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@prettier/parse-srcset": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@prettier/parse-srcset/-/parse-srcset-3.1.0.tgz", + "integrity": "sha512-FIRv2rZotO9NP/r66taYqD1zICpPiBbrECqjKV/xqNotqDxF7fLzzUeK+1RSRx9Tenk0DajR/GcRmTJ2qtHaKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.13", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.13.tgz", @@ -2113,6 +2130,17 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/html-element-attributes": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-3.5.0.tgz", + "integrity": "sha512-rU2BFhp0kQla9sqPBI46C+zbP6PFOtD7z6XNAJ6as+cGecCDXLx0W3aIs6XdPLmBBG/Fy1meRi/n65Exofz4Qw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/html-entities": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", @@ -3056,6 +3084,129 @@ "dev": true, "license": "MIT" }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-blade": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-blade/-/prettier-plugin-blade-3.2.2.tgz", + "integrity": "sha512-CPAlkLTAnvEZfvmRZ1CgdeePpfhxz/Bggei2lSAYcrsBFBhSZ04Ky0ttL4VB1u2q3iKh411vBi0T/Wx3GHWq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@prettier/html-tags": "^2.2.0", + "@prettier/parse-srcset": "^3.1.0", + "html-element-attributes": "^3.5.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@prettier/plugin-php": "^0.24.0", + "prettier": "^3.0.0", + "prettier-plugin-tailwindcss": "^0.7.0 || ^0.8.0" + }, + "peerDependenciesMeta": { + "@prettier/plugin-php": { + "optional": true + }, + "prettier-plugin-tailwindcss": { + "optional": true + } + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.8.1.tgz", + "integrity": "sha512-iaFMYqDsE4ffdDkn5qup0j5f2aCEBFZrdrZnvu9QKTlWx/iGPeQ4HHu7b7fCPMxeo9nwQBiOAh2nSypdFYWJkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "@zackad/prettier-plugin-twig": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + } + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", diff --git a/package.json b/package.json index 17a500b..e0fa9d0 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,9 @@ "concurrently": "^9.0.1", "laravel-vite-plugin": "^3.0.0", "postcss": "8.5.10", + "prettier": "^3.9.6", + "prettier-plugin-blade": "^3.2.2", + "prettier-plugin-tailwindcss": "^0.8.1", "sass": "^1.99.0", "sweetalert2": "^11.26.24", "vite": "^8.0.7" diff --git a/resources/views/components/breadcrumb.blade.php b/resources/views/components/breadcrumb.blade.php index 8e4afb6..a65f5b5 100644 --- a/resources/views/components/breadcrumb.blade.php +++ b/resources/views/components/breadcrumb.blade.php @@ -8,11 +8,12 @@
- diff --git a/resources/views/components/button.blade.php b/resources/views/components/button.blade.php index 9ad9231..694ff2b 100644 --- a/resources/views/components/button.blade.php +++ b/resources/views/components/button.blade.php @@ -11,20 +11,22 @@ ])