i18n: fix widget heading, translate Select options from model consts, +40 keys

- LowStockTable: rename getHeading → getTableHeading (correct Filament API)
- Global I18n::opts() helper wraps Model::CONST values in __() so
  Select dropdowns show translated status/type/season/etc. labels
- Sed-transform ->options(X::CONST), ->options(array_combine(X::A,X::A)),
  and formatStateUsing(fn($s)=>X::CONST[$s]??$s) → wrap with __()
  (58 options + 10 combines + 7 formatStateUsing across 28 files)
- CalendarBoard: all 7 day names now via __() (was missing 4)
- calendar-board.blade: fix untranslated 'săptămâna curentă', 'capacitate',
  'rata confirmare', 'mediu', 'plin', 'Pod / Zi' / 'Mecanic / Zi'
- +40 RU/EN translations (Client & Auto, Maistru / Mecanic, Programat,
  Sosit, Finalizat, Anulat, Neprezentat, days of week, calendar KPIs)

All 306 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 06:42:16 +00:00
parent 272080b274
commit 95aeecb932
33 changed files with 159 additions and 123 deletions
@@ -75,7 +75,7 @@ class SubscriptionResource extends Resource
$set('currency', $plan->currency); $set('currency', $plan->currency);
}), }),
Forms\Components\Select::make('period') Forms\Components\Select::make('period')
->options(Subscription::PERIODS)->default('monthly')->required()->live() ->options(\App\Support\I18n::opts(Subscription::PERIODS))->default('monthly')->required()->live()
->afterStateUpdated(function ($state, Set $set, Get $get) { ->afterStateUpdated(function ($state, Set $set, Get $get) {
$plan = Plan::find($get('plan_id')); $plan = Plan::find($get('plan_id'));
if (! $plan) return; if (! $plan) return;
@@ -88,7 +88,7 @@ class SubscriptionResource extends Resource
$set('period_end', $end); $set('period_end', $end);
}), }),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(Subscription::STATUSES)->default('pending')->required(), ->options(\App\Support\I18n::opts(Subscription::STATUSES))->default('pending')->required(),
]), ]),
Schemas\Components\Section::make(__('Sumă')) Schemas\Components\Section::make(__('Sumă'))
->columns(3) ->columns(3)
@@ -96,7 +96,7 @@ class SubscriptionResource extends Resource
Forms\Components\TextInput::make('amount')->numeric()->required()->suffix(fn (Get $get) => $get('currency') ?? 'MDL'), Forms\Components\TextInput::make('amount')->numeric()->required()->suffix(fn (Get $get) => $get('currency') ?? 'MDL'),
Forms\Components\Select::make('currency')->options(['MDL' => 'MDL', 'EUR' => 'EUR', 'USD' => 'USD'])->default('MDL'), Forms\Components\Select::make('currency')->options(['MDL' => 'MDL', 'EUR' => 'EUR', 'USD' => 'USD'])->default('MDL'),
Forms\Components\Select::make('payment_method') Forms\Components\Select::make('payment_method')
->options(Subscription::PAYMENT_METHODS), ->options(\App\Support\I18n::opts(Subscription::PAYMENT_METHODS)),
]), ]),
Schemas\Components\Section::make(__('Perioadă')) Schemas\Components\Section::make(__('Perioadă'))
->columns(3) ->columns(3)
@@ -151,8 +151,8 @@ class SubscriptionResource extends Resource
Tables\Columns\TextColumn::make('paid_at')->label(__('Plătit'))->date()->placeholder('—'), Tables\Columns\TextColumn::make('paid_at')->label(__('Plătit'))->date()->placeholder('—'),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(Subscription::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(Subscription::STATUSES)),
Tables\Filters\SelectFilter::make('period')->options(Subscription::PERIODS), Tables\Filters\SelectFilter::make('period')->options(\App\Support\I18n::opts(Subscription::PERIODS)),
]) ])
->actions([ ->actions([
Actions\Action::make('mark_paid') Actions\Action::make('mark_paid')
@@ -58,7 +58,7 @@ class SuperAdminResource extends Resource
->columns(1) ->columns(1)
->schema([ ->schema([
Forms\Components\Select::make('role') Forms\Components\Select::make('role')
->options(SuperAdmin::ROLES) ->options(\App\Support\I18n::opts(SuperAdmin::ROLES))
->default('support') ->default('support')
->required() ->required()
->helperText(__('Owner = drepturi totale. Admin = aproape la fel. Sales = doar tenanți + planuri. Finance = facturi. Support = read-only.')), ->helperText(__('Owner = drepturi totale. Admin = aproape la fel. Sales = doar tenanți + planuri. Finance = facturi. Support = read-only.')),
@@ -115,7 +115,7 @@ class SuperAdminResource extends Resource
Tables\Columns\TextColumn::make('created_at')->date(), Tables\Columns\TextColumn::make('created_at')->date(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('role')->options(SuperAdmin::ROLES), Tables\Filters\SelectFilter::make('role')->options(\App\Support\I18n::opts(SuperAdmin::ROLES)),
Tables\Filters\TernaryFilter::make('is_active')->label(__('Activ')), Tables\Filters\TernaryFilter::make('is_active')->label(__('Activ')),
]) ])
->actions([ ->actions([
+1 -1
View File
@@ -118,7 +118,7 @@ class CalendarBoard extends Page
public function getDays(): array public function getDays(): array
{ {
$today = Carbon::today()->toDateString(); $today = Carbon::today()->toDateString();
$names = ['Luni', __('Marți'), 'Miercuri', 'Joi', 'Vineri', __('Sâmbătă'), __('Duminică')]; $names = [__('Luni'), __('Marți'), __('Miercuri'), __('Joi'), __('Vineri'), __('Sâmbătă'), __('Duminică')];
$start = Carbon::parse($this->weekStart); $start = Carbon::parse($this->weekStart);
$count = match ($this->viewMode) { $count = match ($this->viewMode) {
@@ -66,7 +66,7 @@ class AppointmentResource extends Resource
->options(fn () => User::pluck('name', 'id')) ->options(fn () => User::pluck('name', 'id'))
->searchable(), ->searchable(),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(Appointment::STATUSES) ->options(\App\Support\I18n::opts(Appointment::STATUSES))
->default('scheduled') ->default('scheduled')
->required(), ->required(),
]), ]),
@@ -103,7 +103,7 @@ class AppointmentResource extends Resource
Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'), Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'),
Tables\Columns\TextColumn::make('master.name')->label(__('Maistru'))->placeholder('—'), Tables\Columns\TextColumn::make('master.name')->label(__('Maistru'))->placeholder('—'),
Tables\Columns\TextColumn::make('status') Tables\Columns\TextColumn::make('status')
->formatStateUsing(fn ($state) => Appointment::STATUSES[$state] ?? $state) ->formatStateUsing(fn ($state) => __(Appointment::STATUSES[$state] ?? $state))
->badge() ->badge()
->colors([ ->colors([
'gray' => ['scheduled'], 'gray' => ['scheduled'],
@@ -119,7 +119,7 @@ class AppointmentResource extends Resource
Tables\Filters\Filter::make('upcoming') Tables\Filters\Filter::make('upcoming')
->label(__('Viitoare')) ->label(__('Viitoare'))
->query(fn ($q) => $q->where('date', '>=', today())), ->query(fn ($q) => $q->where('date', '>=', today())),
Tables\Filters\SelectFilter::make('status')->options(Appointment::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(Appointment::STATUSES)),
Tables\Filters\SelectFilter::make('post_id') Tables\Filters\SelectFilter::make('post_id')
->label(__('Pod')) ->label(__('Pod'))
->options(fn () => Post::pluck('name', 'id')), ->options(fn () => Post::pluck('name', 'id')),
@@ -48,8 +48,8 @@ class BodyshopJobResource extends Resource
->columns(3) ->columns(3)
->schema([ ->schema([
Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder(__('Generat automat')), Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder(__('Generat automat')),
Forms\Components\Select::make('type')->label(__('Tip'))->options(BodyshopJob::TYPES)->default('body_repair')->required(), Forms\Components\Select::make('type')->label(__('Tip'))->options(\App\Support\I18n::opts(BodyshopJob::TYPES))->default('body_repair')->required(),
Forms\Components\Select::make('status')->label(__('Status'))->options(BodyshopJob::STATUSES)->default('estimate')->required(), Forms\Components\Select::make('status')->label(__('Status'))->options(\App\Support\I18n::opts(BodyshopJob::STATUSES))->default('estimate')->required(),
Forms\Components\Select::make('client_id') Forms\Components\Select::make('client_id')
->label(__('Client')) ->label(__('Client'))
->options(fn () => Client::pluck('name', 'id')) ->options(fn () => Client::pluck('name', 'id'))
@@ -76,7 +76,7 @@ class BodyshopJobResource extends Resource
Forms\Components\TextInput::make('claim_no')->label(__('Nr. dosar daună')) Forms\Components\TextInput::make('claim_no')->label(__('Nr. dosar daună'))
->visible(fn (Get $get) => $get('is_insurance')), ->visible(fn (Get $get) => $get('is_insurance')),
Forms\Components\Select::make('insurance_status')->label(__('Status dosar')) Forms\Components\Select::make('insurance_status')->label(__('Status dosar'))
->options(BodyshopJob::INSURANCE_STATUSES) ->options(\App\Support\I18n::opts(BodyshopJob::INSURANCE_STATUSES))
->visible(fn (Get $get) => $get('is_insurance')), ->visible(fn (Get $get) => $get('is_insurance')),
]), ]),
Schemas\Components\Section::make(__('Foto înainte / după')) Schemas\Components\Section::make(__('Foto înainte / după'))
@@ -115,8 +115,8 @@ class BodyshopJobResource extends Resource
]), ]),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('type')->options(BodyshopJob::TYPES), Tables\Filters\SelectFilter::make('type')->options(\App\Support\I18n::opts(BodyshopJob::TYPES)),
Tables\Filters\SelectFilter::make('status')->options(BodyshopJob::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(BodyshopJob::STATUSES)),
Tables\Filters\TernaryFilter::make('is_insurance')->label(__('Caz asigurare')), Tables\Filters\TernaryFilter::make('is_insurance')->label(__('Caz asigurare')),
]) ])
->actions([ ->actions([
@@ -26,16 +26,16 @@ class DamagePointsRelationManager extends RelationManager
return $schema->components([ return $schema->components([
Forms\Components\Select::make('zone') Forms\Components\Select::make('zone')
->label(__('Zonă')) ->label(__('Zonă'))
->options(array_combine(DamagePoint::ZONES, DamagePoint::ZONES)) ->options(\App\Support\I18n::opts(array_combine(DamagePoint::ZONES, DamagePoint::ZONES)))
->searchable() ->searchable()
->required(), ->required(),
Forms\Components\Select::make('kind') Forms\Components\Select::make('kind')
->label(__('Tip daună')) ->label(__('Tip daună'))
->options(array_combine(DamagePoint::KINDS, DamagePoint::KINDS)) ->options(\App\Support\I18n::opts(array_combine(DamagePoint::KINDS, DamagePoint::KINDS)))
->required(), ->required(),
Forms\Components\Select::make('severity') Forms\Components\Select::make('severity')
->label(__('Gravitate')) ->label(__('Gravitate'))
->options(DamagePoint::SEVERITIES) ->options(\App\Support\I18n::opts(DamagePoint::SEVERITIES))
->default('minor') ->default('minor')
->required(), ->required(),
Forms\Components\Textarea::make('notes')->label(__('Observații'))->rows(2)->columnSpanFull(), Forms\Components\Textarea::make('notes')->label(__('Observații'))->rows(2)->columnSpanFull(),
@@ -53,12 +53,12 @@ class CallResource extends Resource
->schema([ ->schema([
Forms\Components\DateTimePicker::make('called_at')->label(__('Data & ora'))->default(now())->required(), Forms\Components\DateTimePicker::make('called_at')->label(__('Data & ora'))->default(now())->required(),
Forms\Components\Select::make('direction') Forms\Components\Select::make('direction')
->options(Call::DIRECTIONS) ->options(\App\Support\I18n::opts(Call::DIRECTIONS))
->default('incoming') ->default('incoming')
->required(), ->required(),
Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->required()->maxLength(40), Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->required()->maxLength(40),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(Call::STATUSES) ->options(\App\Support\I18n::opts(Call::STATUSES))
->default('answered') ->default('answered')
->required(), ->required(),
Forms\Components\TextInput::make('duration_sec')->label(__('Durată (sec)'))->numeric()->default(0), Forms\Components\TextInput::make('duration_sec')->label(__('Durată (sec)'))->numeric()->default(0),
@@ -92,7 +92,7 @@ class CallResource extends Resource
->badge(), ->badge(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('direction')->options(Call::DIRECTIONS), Tables\Filters\SelectFilter::make('direction')->options(\App\Support\I18n::opts(Call::DIRECTIONS)),
Tables\Filters\Filter::make('today') Tables\Filters\Filter::make('today')
->label(__('Astăzi')) ->label(__('Astăzi'))
->query(fn ($q) => $q->whereDate('called_at', today())), ->query(fn ($q) => $q->whereDate('called_at', today())),
@@ -73,11 +73,11 @@ class DealResource extends Resource
Forms\Components\TextInput::make('name')->label(__('Subiect'))->required()->maxLength(160), Forms\Components\TextInput::make('name')->label(__('Subiect'))->required()->maxLength(160),
Forms\Components\TextInput::make('price')->label(__('Valoare'))->numeric()->default(0), Forms\Components\TextInput::make('price')->label(__('Valoare'))->numeric()->default(0),
Forms\Components\Select::make('stage') Forms\Components\Select::make('stage')
->options(Deal::STAGES) ->options(\App\Support\I18n::opts(Deal::STAGES))
->default('new') ->default('new')
->required(), ->required(),
Forms\Components\Select::make('source') Forms\Components\Select::make('source')
->options(Lead::SOURCES) ->options(\App\Support\I18n::opts(Lead::SOURCES))
->searchable(), ->searchable(),
Forms\Components\Select::make('assigned_to') Forms\Components\Select::make('assigned_to')
->label(__('Responsabil')) ->label(__('Responsabil'))
@@ -97,7 +97,7 @@ class DealResource extends Resource
Tables\Columns\TextColumn::make('client.name')->label(__('Client'))->searchable(), Tables\Columns\TextColumn::make('client.name')->label(__('Client'))->searchable(),
Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'), Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'),
Tables\Columns\TextColumn::make('stage') Tables\Columns\TextColumn::make('stage')
->formatStateUsing(fn ($state) => Deal::STAGES[$state] ?? $state) ->formatStateUsing(fn ($state) => __(Deal::STAGES[$state] ?? $state))
->badge() ->badge()
->colors([ ->colors([
'gray' => ['new'], 'gray' => ['new'],
@@ -107,12 +107,12 @@ class DealResource extends Resource
'danger' => ['lost'], 'danger' => ['lost'],
]), ]),
Tables\Columns\TextColumn::make('price')->money('MDL')->sortable(), Tables\Columns\TextColumn::make('price')->money('MDL')->sortable(),
Tables\Columns\TextColumn::make('source')->label(__('Sursă'))->formatStateUsing(fn ($state) => Lead::SOURCES[$state] ?? $state)->placeholder('—'), Tables\Columns\TextColumn::make('source')->label(__('Sursă'))->formatStateUsing(fn ($state) => __(Lead::SOURCES[$state] ?? $state))->placeholder('—'),
Tables\Columns\TextColumn::make('assignedTo.name')->label(__('Responsabil'))->placeholder('—'), Tables\Columns\TextColumn::make('assignedTo.name')->label(__('Responsabil'))->placeholder('—'),
Tables\Columns\TextColumn::make('created_at')->date()->sortable(), Tables\Columns\TextColumn::make('created_at')->date()->sortable(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('stage')->options(Deal::STAGES), Tables\Filters\SelectFilter::make('stage')->options(\App\Support\I18n::opts(Deal::STAGES)),
Tables\Filters\SelectFilter::make('assigned_to') Tables\Filters\SelectFilter::make('assigned_to')
->label(__('Responsabil')) ->label(__('Responsabil'))
->options(fn () => User::pluck('name', 'id')), ->options(fn () => User::pluck('name', 'id')),
@@ -63,13 +63,13 @@ class ExpenseResource extends Resource
->schema([ ->schema([
Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(), Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(),
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->options(Expense::CATEGORIES) ->options(\App\Support\I18n::opts(Expense::CATEGORIES))
->default('other') ->default('other')
->required(), ->required(),
Forms\Components\TextInput::make('name')->label(__('Denumire'))->required()->maxLength(160)->columnSpanFull(), Forms\Components\TextInput::make('name')->label(__('Denumire'))->required()->maxLength(160)->columnSpanFull(),
Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(), Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(),
Forms\Components\Select::make('method') Forms\Components\Select::make('method')
->options(Expense::METHODS) ->options(\App\Support\I18n::opts(Expense::METHODS))
->default('cash') ->default('cash')
->required(), ->required(),
Forms\Components\Select::make('supplier_id') Forms\Components\Select::make('supplier_id')
@@ -99,7 +99,7 @@ class ExpenseResource extends Resource
->summarize(Tables\Columns\Summarizers\Sum::make()->money('MDL')->label(__('Total'))), ->summarize(Tables\Columns\Summarizers\Sum::make()->money('MDL')->label(__('Total'))),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('category')->options(Expense::CATEGORIES), Tables\Filters\SelectFilter::make('category')->options(\App\Support\I18n::opts(Expense::CATEGORIES)),
Tables\Filters\Filter::make('this_month') Tables\Filters\Filter::make('this_month')
->label(__('Luna curentă')) ->label(__('Luna curentă'))
->query(fn ($q) => $q->whereMonth('paid_at', now()->month)->whereYear('paid_at', now()->year)), ->query(fn ($q) => $q->whereMonth('paid_at', now()->month)->whereYear('paid_at', now()->year)),
@@ -53,7 +53,7 @@ class LaborResource extends Resource
->schema([ ->schema([
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->label(__('Categorie')) ->label(__('Categorie'))
->options(array_combine(Labor::CATEGORIES, Labor::CATEGORIES)) ->options(\App\Support\I18n::opts(array_combine(Labor::CATEGORIES, Labor::CATEGORIES)))
->required() ->required()
->searchable(), ->searchable(),
Forms\Components\TextInput::make('code')->label(__('Cod'))->maxLength(32), Forms\Components\TextInput::make('code')->label(__('Cod'))->maxLength(32),
@@ -61,7 +61,7 @@ class LaborResource extends Resource
Forms\Components\TextInput::make('name_ru')->label(__('Nume (RU)'))->maxLength(160), Forms\Components\TextInput::make('name_ru')->label(__('Nume (RU)'))->maxLength(160),
Forms\Components\Select::make('pricing_mode') Forms\Components\Select::make('pricing_mode')
->label(__('Mod tarifare')) ->label(__('Mod tarifare'))
->options(Labor::PRICING_MODES) ->options(\App\Support\I18n::opts(Labor::PRICING_MODES))
->default('hourly') ->default('hourly')
->live() ->live()
->required(), ->required(),
@@ -95,7 +95,7 @@ class LaborResource extends Resource
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('category') Tables\Filters\SelectFilter::make('category')
->options(array_combine(Labor::CATEGORIES, Labor::CATEGORIES)), ->options(\App\Support\I18n::opts(array_combine(Labor::CATEGORIES, Labor::CATEGORIES))),
Tables\Filters\TernaryFilter::make('is_active')->label(__('Doar active')), Tables\Filters\TernaryFilter::make('is_active')->label(__('Doar active')),
]) ])
->actions([ ->actions([
@@ -69,7 +69,7 @@ class LeadResource extends Resource
Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->required()->maxLength(40), Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->required()->maxLength(40),
Forms\Components\TextInput::make('email')->email()->maxLength(120), Forms\Components\TextInput::make('email')->email()->maxLength(120),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(Lead::STATUSES) ->options(\App\Support\I18n::opts(Lead::STATUSES))
->default('new') ->default('new')
->required(), ->required(),
]), ]),
@@ -84,7 +84,7 @@ class LeadResource extends Resource
->columns(2) ->columns(2)
->schema([ ->schema([
Forms\Components\Select::make('source') Forms\Components\Select::make('source')
->options(Lead::SOURCES) ->options(\App\Support\I18n::opts(Lead::SOURCES))
->searchable() ->searchable()
->default('manual'), ->default('manual'),
Forms\Components\Select::make('assigned_to') Forms\Components\Select::make('assigned_to')
@@ -115,9 +115,9 @@ class LeadResource extends Resource
Tables\Columns\TextColumn::make('name')->searchable()->sortable(), Tables\Columns\TextColumn::make('name')->searchable()->sortable(),
Tables\Columns\TextColumn::make('phone')->copyable()->searchable(), Tables\Columns\TextColumn::make('phone')->copyable()->searchable(),
Tables\Columns\TextColumn::make('car')->label(__('Auto'))->formatStateUsing(fn ($state, $record) => trim($state . ' ' . ($record->model ?? ''))), Tables\Columns\TextColumn::make('car')->label(__('Auto'))->formatStateUsing(fn ($state, $record) => trim($state . ' ' . ($record->model ?? ''))),
Tables\Columns\TextColumn::make('source')->label(__('Sursă'))->formatStateUsing(fn ($state) => Lead::SOURCES[$state] ?? $state)->badge(), Tables\Columns\TextColumn::make('source')->label(__('Sursă'))->formatStateUsing(fn ($state) => __(Lead::SOURCES[$state] ?? $state))->badge(),
Tables\Columns\TextColumn::make('status') Tables\Columns\TextColumn::make('status')
->formatStateUsing(fn ($state) => Lead::STATUSES[$state] ?? $state) ->formatStateUsing(fn ($state) => __(Lead::STATUSES[$state] ?? $state))
->badge() ->badge()
->colors([ ->colors([
'gray' => ['new'], 'gray' => ['new'],
@@ -130,8 +130,8 @@ class LeadResource extends Resource
Tables\Columns\TextColumn::make('budget')->money('MDL')->placeholder('—'), Tables\Columns\TextColumn::make('budget')->money('MDL')->placeholder('—'),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(Lead::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(Lead::STATUSES)),
Tables\Filters\SelectFilter::make('source')->options(Lead::SOURCES), Tables\Filters\SelectFilter::make('source')->options(\App\Support\I18n::opts(Lead::SOURCES)),
]) ])
->actions([ ->actions([
Actions\Action::make('convert') Actions\Action::make('convert')
@@ -55,7 +55,7 @@ class MarkupRuleResource extends Resource
->schema([ ->schema([
Forms\Components\Select::make('type') Forms\Components\Select::make('type')
->label(__('Tip')) ->label(__('Tip'))
->options(MarkupRule::TYPES) ->options(\App\Support\I18n::opts(MarkupRule::TYPES))
->default('category') ->default('category')
->required() ->required()
->live(), ->live(),
@@ -110,7 +110,7 @@ class MarkupRuleResource extends Resource
Tables\Columns\IconColumn::make('is_active')->boolean(), Tables\Columns\IconColumn::make('is_active')->boolean(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('type')->options(MarkupRule::TYPES), Tables\Filters\SelectFilter::make('type')->options(\App\Support\I18n::opts(MarkupRule::TYPES)),
]) ])
->headerActions([ ->headerActions([
Actions\Action::make('apply_all') Actions\Action::make('apply_all')
@@ -52,7 +52,7 @@ class MessageTemplateResource extends Resource
->schema([ ->schema([
Forms\Components\TextInput::make('name')->label(__('Nume template'))->required()->maxLength(120), Forms\Components\TextInput::make('name')->label(__('Nume template'))->required()->maxLength(120),
Forms\Components\Select::make('channel') Forms\Components\Select::make('channel')
->options(MessageTemplate::CHANNELS) ->options(\App\Support\I18n::opts(MessageTemplate::CHANNELS))
->default('telegram') ->default('telegram')
->required(), ->required(),
Forms\Components\TextInput::make('subject')->label(__('Subiect (email)'))->maxLength(160)->columnSpanFull(), Forms\Components\TextInput::make('subject')->label(__('Subiect (email)'))->maxLength(160)->columnSpanFull(),
@@ -82,7 +82,7 @@ class MessageTemplateResource extends Resource
Tables\Columns\IconColumn::make('is_active')->boolean(), Tables\Columns\IconColumn::make('is_active')->boolean(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('channel')->options(MessageTemplate::CHANNELS), Tables\Filters\SelectFilter::make('channel')->options(\App\Support\I18n::opts(MessageTemplate::CHANNELS)),
]) ])
->actions([ ->actions([
Actions\EditAction::make(), Actions\EditAction::make(),
@@ -64,8 +64,8 @@ class OnlineOrderResource extends Resource
->columns(3) ->columns(3)
->schema([ ->schema([
Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false), Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false),
Forms\Components\Select::make('status')->options(OnlineOrder::STATUSES)->required(), Forms\Components\Select::make('status')->options(\App\Support\I18n::opts(OnlineOrder::STATUSES))->required(),
Forms\Components\Select::make('delivery_method')->label(__('Livrare'))->options(OnlineOrder::DELIVERY)->required(), Forms\Components\Select::make('delivery_method')->label(__('Livrare'))->options(\App\Support\I18n::opts(OnlineOrder::DELIVERY))->required(),
Forms\Components\TextInput::make('customer_name')->label(__('Client'))->required(), Forms\Components\TextInput::make('customer_name')->label(__('Client'))->required(),
Forms\Components\TextInput::make('customer_phone')->label(__('Telefon'))->required(), Forms\Components\TextInput::make('customer_phone')->label(__('Telefon'))->required(),
Forms\Components\TextInput::make('customer_email')->label(__('Email')), Forms\Components\TextInput::make('customer_email')->label(__('Email')),
@@ -100,7 +100,7 @@ class OnlineOrderResource extends Resource
Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight()->sortable(), Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight()->sortable(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(OnlineOrder::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(OnlineOrder::STATUSES)),
]) ])
->actions([ ->actions([
Actions\Action::make('fulfill') Actions\Action::make('fulfill')
@@ -84,7 +84,7 @@ class PartResource extends Resource
Forms\Components\TextInput::make('brand')->maxLength(64), Forms\Components\TextInput::make('brand')->maxLength(64),
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->label(__('Categorie')) ->label(__('Categorie'))
->options(array_combine(Part::CATEGORIES, Part::CATEGORIES)) ->options(\App\Support\I18n::opts(array_combine(Part::CATEGORIES, Part::CATEGORIES)))
->searchable(), ->searchable(),
Forms\Components\TextInput::make('barcode')->label(__('Cod bare'))->maxLength(64), Forms\Components\TextInput::make('barcode')->label(__('Cod bare'))->maxLength(64),
Forms\Components\TextInput::make('location')->label(__('Locație rack/bin'))->maxLength(64), Forms\Components\TextInput::make('location')->label(__('Locație rack/bin'))->maxLength(64),
@@ -167,7 +167,7 @@ class PartResource extends Resource
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('category') Tables\Filters\SelectFilter::make('category')
->options(array_combine(Part::CATEGORIES, Part::CATEGORIES)), ->options(\App\Support\I18n::opts(array_combine(Part::CATEGORIES, Part::CATEGORIES))),
Tables\Filters\Filter::make('low_stock') Tables\Filters\Filter::make('low_stock')
->label(__('Stoc minim')) ->label(__('Stoc minim'))
->query(fn ($q) => $q->whereColumn('qty', '<=', 'min_qty')), ->query(fn ($q) => $q->whereColumn('qty', '<=', 'min_qty')),
@@ -69,7 +69,7 @@ class PaymentResource extends Resource
->schema([ ->schema([
Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(), Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(),
Forms\Components\Select::make('method') Forms\Components\Select::make('method')
->options(Payment::METHODS) ->options(\App\Support\I18n::opts(Payment::METHODS))
->default('cash') ->default('cash')
->required(), ->required(),
Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(), Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(),
@@ -104,7 +104,7 @@ class PaymentResource extends Resource
Tables\Columns\TextColumn::make('reference')->label(__('Ref.'))->placeholder('—')->toggleable(), Tables\Columns\TextColumn::make('reference')->label(__('Ref.'))->placeholder('—')->toggleable(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('method')->options(Payment::METHODS), Tables\Filters\SelectFilter::make('method')->options(\App\Support\I18n::opts(Payment::METHODS)),
Tables\Filters\Filter::make('today') Tables\Filters\Filter::make('today')
->label(__('Astăzi')) ->label(__('Astăzi'))
->query(fn ($q) => $q->whereDate('paid_at', today())), ->query(fn ($q) => $q->whereDate('paid_at', today())),
@@ -67,7 +67,7 @@ class PayrollAdjustmentResource extends Resource
->searchable() ->searchable()
->required(), ->required(),
Forms\Components\Select::make('type') Forms\Components\Select::make('type')
->options(PayrollAdjustment::TYPES) ->options(\App\Support\I18n::opts(PayrollAdjustment::TYPES))
->default('bonus') ->default('bonus')
->required(), ->required(),
Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(), Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(),
@@ -102,7 +102,7 @@ class PayrollAdjustmentResource extends Resource
Tables\Columns\IconColumn::make('applied')->boolean()->label(__('Aplicat')), Tables\Columns\IconColumn::make('applied')->boolean()->label(__('Aplicat')),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('type')->options(PayrollAdjustment::TYPES), Tables\Filters\SelectFilter::make('type')->options(\App\Support\I18n::opts(PayrollAdjustment::TYPES)),
Tables\Filters\SelectFilter::make('user_id') Tables\Filters\SelectFilter::make('user_id')
->label(__('Utilizator')) ->label(__('Utilizator'))
->options(fn () => User::pluck('name', 'id')), ->options(fn () => User::pluck('name', 'id')),
@@ -57,7 +57,7 @@ class PricingCoefficientResource extends Resource
->schema([ ->schema([
Forms\Components\CheckboxList::make('conditions.classes') Forms\Components\CheckboxList::make('conditions.classes')
->label(__('Clase auto')) ->label(__('Clase auto'))
->options(PricingCoefficient::VEHICLE_CLASSES) ->options(\App\Support\I18n::opts(PricingCoefficient::VEHICLE_CLASSES))
->columns(2) ->columns(2)
->columnSpanFull(), ->columnSpanFull(),
Forms\Components\CheckboxList::make('conditions.body_types') Forms\Components\CheckboxList::make('conditions.body_types')
@@ -75,7 +75,7 @@ class PricingCoefficientResource extends Resource
Forms\Components\Toggle::make('conditions.client_vip')->label(__('Doar clienți VIP')), Forms\Components\Toggle::make('conditions.client_vip')->label(__('Doar clienți VIP')),
Forms\Components\CheckboxList::make('conditions.urgency') Forms\Components\CheckboxList::make('conditions.urgency')
->label(__('Urgență')) ->label(__('Urgență'))
->options(PricingCoefficient::URGENCY) ->options(\App\Support\I18n::opts(PricingCoefficient::URGENCY))
->columns(3) ->columns(3)
->columnSpanFull(), ->columnSpanFull(),
]), ]),
@@ -66,7 +66,7 @@ class PurchaseResource extends Resource
->default(fn () => Warehouse::where('is_default', true)->value('id')) ->default(fn () => Warehouse::where('is_default', true)->value('id'))
->required(), ->required(),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(Purchase::STATUSES) ->options(\App\Support\I18n::opts(Purchase::STATUSES))
->default('draft') ->default('draft')
->required(), ->required(),
Forms\Components\DatePicker::make('order_date')->label(__('Data comandă'))->default(today())->required(), Forms\Components\DatePicker::make('order_date')->label(__('Data comandă'))->default(today())->required(),
@@ -109,7 +109,7 @@ class PurchaseResource extends Resource
Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight(), Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(Purchase::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(Purchase::STATUSES)),
Tables\Filters\SelectFilter::make('supplier_id') Tables\Filters\SelectFilter::make('supplier_id')
->label(__('Furnizor')) ->label(__('Furnizor'))
->options(fn () => Supplier::pluck('name', 'id')), ->options(fn () => Supplier::pluck('name', 'id')),
@@ -56,7 +56,7 @@ class ServiceTemplateResource extends Resource
->placeholder(__('ex: Revizie completă 15.000 km'))->columnSpanFull(), ->placeholder(__('ex: Revizie completă 15.000 km'))->columnSpanFull(),
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->label(__('Categorie')) ->label(__('Categorie'))
->options(array_combine(Labor::CATEGORIES, Labor::CATEGORIES)) ->options(\App\Support\I18n::opts(array_combine(Labor::CATEGORIES, Labor::CATEGORIES)))
->searchable(), ->searchable(),
Forms\Components\Toggle::make('is_active')->label(__('Activ'))->default(true), Forms\Components\Toggle::make('is_active')->label(__('Activ'))->default(true),
Forms\Components\Textarea::make('notes')->label(__('Observații'))->columnSpanFull()->rows(2), Forms\Components\Textarea::make('notes')->label(__('Observații'))->columnSpanFull()->rows(2),
@@ -30,7 +30,7 @@ class ItemsRelationManager extends RelationManager
return $schema->components([ return $schema->components([
Forms\Components\Select::make('kind') Forms\Components\Select::make('kind')
->label(__('Tip')) ->label(__('Tip'))
->options(ServiceTemplateItem::KINDS) ->options(\App\Support\I18n::opts(ServiceTemplateItem::KINDS))
->default('labor') ->default('labor')
->live() ->live()
->required(), ->required(),
@@ -45,7 +45,7 @@ class SubcontractJobResource extends Resource
->columns(2) ->columns(2)
->schema([ ->schema([
Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder(__('Generat automat')), Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder(__('Generat automat')),
Forms\Components\Select::make('status')->options(SubcontractJob::STATUSES)->default('sent')->required(), Forms\Components\Select::make('status')->options(\App\Support\I18n::opts(SubcontractJob::STATUSES))->default('sent')->required(),
Forms\Components\Select::make('subcontractor_id') Forms\Components\Select::make('subcontractor_id')
->label(__('Subcontractor')) ->label(__('Subcontractor'))
->options(fn () => Subcontractor::where('is_active', true)->pluck('name', 'id')) ->options(fn () => Subcontractor::where('is_active', true)->pluck('name', 'id'))
@@ -57,7 +57,7 @@ class SubcontractJobResource extends Resource
->searchable(), ->searchable(),
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->label(__('Categorie')) ->label(__('Categorie'))
->options(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)) ->options(\App\Support\I18n::opts(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)))
->searchable(), ->searchable(),
Forms\Components\Textarea::make('description')->label(__('Descriere'))->rows(2)->columnSpanFull(), Forms\Components\Textarea::make('description')->label(__('Descriere'))->rows(2)->columnSpanFull(),
]), ]),
@@ -109,7 +109,7 @@ class SubcontractJobResource extends Resource
Tables\Columns\IconColumn::make('paid_to_sub')->label(__('Plătit terț'))->boolean()->toggleable(), Tables\Columns\IconColumn::make('paid_to_sub')->label(__('Plătit terț'))->boolean()->toggleable(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(SubcontractJob::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(SubcontractJob::STATUSES)),
Tables\Filters\SelectFilter::make('subcontractor_id') Tables\Filters\SelectFilter::make('subcontractor_id')
->label(__('Subcontractor')) ->label(__('Subcontractor'))
->options(fn () => Subcontractor::pluck('name', 'id')), ->options(fn () => Subcontractor::pluck('name', 'id')),
@@ -41,7 +41,7 @@ class SubcontractorResource extends Resource
Forms\Components\TextInput::make('name')->label(__('Nume'))->required()->maxLength(160), Forms\Components\TextInput::make('name')->label(__('Nume'))->required()->maxLength(160),
Forms\Components\Select::make('specialty') Forms\Components\Select::make('specialty')
->label(__('Specialitate')) ->label(__('Specialitate'))
->options(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)) ->options(\App\Support\I18n::opts(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)))
->searchable(), ->searchable(),
Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->maxLength(40), Forms\Components\TextInput::make('phone')->label(__('Telefon'))->tel()->maxLength(40),
Forms\Components\TextInput::make('email')->email()->maxLength(120), Forms\Components\TextInput::make('email')->email()->maxLength(120),
@@ -65,7 +65,7 @@ class TireSetResource extends Resource
: []) : [])
->searchable(), ->searchable(),
Forms\Components\TextInput::make('label')->label(__('Etichetă'))->placeholder(__('ex: Iarnă Michelin')), Forms\Components\TextInput::make('label')->label(__('Etichetă'))->placeholder(__('ex: Iarnă Michelin')),
Forms\Components\Select::make('season')->label(__('Sezon'))->options(TireSet::SEASONS)->default('winter')->required(), Forms\Components\Select::make('season')->label(__('Sezon'))->options(\App\Support\I18n::opts(TireSet::SEASONS))->default('winter')->required(),
]), ]),
Schemas\Components\Section::make(__('Specificații')) Schemas\Components\Section::make(__('Specificații'))
->columns(3) ->columns(3)
@@ -78,7 +78,7 @@ class TireSetResource extends Resource
Forms\Components\TextInput::make('dot_year')->label(__('DOT'))->maxLength(8)->placeholder('3621'), Forms\Components\TextInput::make('dot_year')->label(__('DOT'))->maxLength(8)->placeholder('3621'),
Forms\Components\Toggle::make('has_rims')->label(__('Cu jante')), Forms\Components\Toggle::make('has_rims')->label(__('Cu jante')),
Forms\Components\Select::make('rim_type')->label(__('Tip jante'))->options(['steel' => __('Tablă'), 'alloy' => 'Aliaj']), Forms\Components\Select::make('rim_type')->label(__('Tip jante'))->options(['steel' => __('Tablă'), 'alloy' => 'Aliaj']),
Forms\Components\Select::make('condition')->label(__('Stare'))->options(TireSet::CONDITIONS), Forms\Components\Select::make('condition')->label(__('Stare'))->options(\App\Support\I18n::opts(TireSet::CONDITIONS)),
]), ]),
Schemas\Components\Section::make(__('Uzură (mm) per poziție')) Schemas\Components\Section::make(__('Uzură (mm) per poziție'))
->columns(4) ->columns(4)
@@ -130,7 +130,7 @@ class TireSetResource extends Resource
->color(fn ($state) => $state === '—' ? 'gray' : 'success'), ->color(fn ($state) => $state === '—' ? 'gray' : 'success'),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('season')->options(TireSet::SEASONS), Tables\Filters\SelectFilter::make('season')->options(\App\Support\I18n::opts(TireSet::SEASONS)),
Tables\Filters\Filter::make('stored') Tables\Filters\Filter::make('stored')
->label(__('În depozit')) ->label(__('În depozit'))
->query(fn ($q) => $q->whereHas('storage', fn ($s) => $s->where('status', 'stored'))), ->query(fn ($q) => $q->whereHas('storage', fn ($s) => $s->where('status', 'stored'))),
@@ -80,7 +80,7 @@ class WorkOrderResource extends Resource
->schema([ ->schema([
Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder('auto'), Forms\Components\TextInput::make('number')->label(__('Nr.'))->disabled()->dehydrated(false)->placeholder('auto'),
Forms\Components\DatePicker::make('opened_at')->label(__('Deschis'))->default(today())->required(), Forms\Components\DatePicker::make('opened_at')->label(__('Deschis'))->default(today())->required(),
Forms\Components\Select::make('status')->options(WorkOrder::STATUSES)->default('new')->required(), Forms\Components\Select::make('status')->options(\App\Support\I18n::opts(WorkOrder::STATUSES))->default('new')->required(),
Forms\Components\Select::make('urgency')->label(__('Urgență')) Forms\Components\Select::make('urgency')->label(__('Urgență'))
->options(\App\Models\Tenant\PricingCoefficient::URGENCY)->default('normal')->required(), ->options(\App\Models\Tenant\PricingCoefficient::URGENCY)->default('normal')->required(),
Forms\Components\Select::make('client_id')->label(__('Client')) Forms\Components\Select::make('client_id')->label(__('Client'))
@@ -128,7 +128,7 @@ class WorkOrderResource extends Resource
Schemas\Components\Section::make(__('Plată & total')) Schemas\Components\Section::make(__('Plată & total'))
->columns(3)->collapsible()->collapsed()->compact() ->columns(3)->collapsible()->collapsed()->compact()
->schema([ ->schema([
Forms\Components\Select::make('pay_status')->options(WorkOrder::PAY_STATUSES)->default('unpaid')->required(), Forms\Components\Select::make('pay_status')->options(\App\Support\I18n::opts(WorkOrder::PAY_STATUSES))->default('unpaid')->required(),
Forms\Components\TextInput::make('discount_pct')->label(__('Discount %'))->numeric()->default(0), Forms\Components\TextInput::make('discount_pct')->label(__('Discount %'))->numeric()->default(0),
Forms\Components\Toggle::make('apply_margin') Forms\Components\Toggle::make('apply_margin')
->label(__('Aplică marjă internă')) ->label(__('Aplică marjă internă'))
@@ -157,7 +157,7 @@ class WorkOrderResource extends Resource
Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'), Tables\Columns\TextColumn::make('vehicle.plate')->label(__('Auto'))->placeholder('—'),
Tables\Columns\TextColumn::make('master.name')->label(__('Maistru'))->placeholder('—'), Tables\Columns\TextColumn::make('master.name')->label(__('Maistru'))->placeholder('—'),
Tables\Columns\TextColumn::make('status') Tables\Columns\TextColumn::make('status')
->formatStateUsing(fn ($state) => WorkOrder::STATUSES[$state] ?? $state) ->formatStateUsing(fn ($state) => __(WorkOrder::STATUSES[$state] ?? $state))
->badge() ->badge()
->colors([ ->colors([
'gray' => ['new'], 'gray' => ['new'],
@@ -167,7 +167,7 @@ class WorkOrderResource extends Resource
'danger' => ['cancelled'], 'danger' => ['cancelled'],
]), ]),
Tables\Columns\TextColumn::make('pay_status') Tables\Columns\TextColumn::make('pay_status')
->formatStateUsing(fn ($state) => WorkOrder::PAY_STATUSES[$state] ?? $state) ->formatStateUsing(fn ($state) => __(WorkOrder::PAY_STATUSES[$state] ?? $state))
->badge() ->badge()
->colors([ ->colors([
'danger' => ['unpaid'], 'danger' => ['unpaid'],
@@ -177,8 +177,8 @@ class WorkOrderResource extends Resource
Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight()->sortable(), Tables\Columns\TextColumn::make('total')->money('MDL')->alignRight()->sortable(),
]) ])
->filters([ ->filters([
Tables\Filters\SelectFilter::make('status')->options(WorkOrder::STATUSES), Tables\Filters\SelectFilter::make('status')->options(\App\Support\I18n::opts(WorkOrder::STATUSES)),
Tables\Filters\SelectFilter::make('pay_status')->options(WorkOrder::PAY_STATUSES), Tables\Filters\SelectFilter::make('pay_status')->options(\App\Support\I18n::opts(WorkOrder::PAY_STATUSES)),
Tables\Filters\SelectFilter::make('master_id') Tables\Filters\SelectFilter::make('master_id')
->label(__('Maistru')) ->label(__('Maistru'))
->options(fn () => User::pluck('name', 'id')), ->options(fn () => User::pluck('name', 'id')),
@@ -57,7 +57,7 @@ class PartsRelationManager extends RelationManager
Forms\Components\TextInput::make('sell_price')->label(__('Preț vânzare'))->numeric()->required(), Forms\Components\TextInput::make('sell_price')->label(__('Preț vânzare'))->numeric()->required(),
Forms\Components\TextInput::make('discount_pct')->label(__('Discount %'))->numeric()->default(0), Forms\Components\TextInput::make('discount_pct')->label(__('Discount %'))->numeric()->default(0),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(WorkOrderPart::STATUSES) ->options(\App\Support\I18n::opts(WorkOrderPart::STATUSES))
->default('needed') ->default('needed')
->required() ->required()
->helperText(__('La trecere pe „Montată" se scade automat din stoc.')), ->helperText(__('La trecere pe „Montată" se scade automat din stoc.')),
@@ -27,7 +27,7 @@ class PaymentsRelationManager extends RelationManager
Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(), Forms\Components\DatePicker::make('paid_at')->label(__('Data'))->default(today())->required(),
Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(), Forms\Components\TextInput::make('amount')->label(__('Sumă'))->numeric()->required(),
Forms\Components\Select::make('method') Forms\Components\Select::make('method')
->options(Payment::METHODS) ->options(\App\Support\I18n::opts(Payment::METHODS))
->default('cash') ->default('cash')
->required(), ->required(),
Forms\Components\TextInput::make('reference')->label(__('Referință'))->maxLength(64), Forms\Components\TextInput::make('reference')->label(__('Referință'))->maxLength(64),
@@ -32,9 +32,9 @@ class SubcontractJobsRelationManager extends RelationManager
->columnSpanFull(), ->columnSpanFull(),
Forms\Components\Select::make('category') Forms\Components\Select::make('category')
->label(__('Categorie')) ->label(__('Categorie'))
->options(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)) ->options(\App\Support\I18n::opts(array_combine(Subcontractor::SPECIALTIES, Subcontractor::SPECIALTIES)))
->searchable(), ->searchable(),
Forms\Components\Select::make('status')->options(SubcontractJob::STATUSES)->default('sent')->required(), Forms\Components\Select::make('status')->options(\App\Support\I18n::opts(SubcontractJob::STATUSES))->default('sent')->required(),
Forms\Components\Textarea::make('description')->label(__('Descriere'))->rows(2)->columnSpanFull(), Forms\Components\Textarea::make('description')->label(__('Descriere'))->rows(2)->columnSpanFull(),
Forms\Components\TextInput::make('cost')->label(__('Cost (terț)'))->numeric()->default(0)->required(), Forms\Components\TextInput::make('cost')->label(__('Cost (terț)'))->numeric()->default(0)->required(),
Forms\Components\TextInput::make('markup_pct')->label(__('Markup %'))->numeric()->default(0), Forms\Components\TextInput::make('markup_pct')->label(__('Markup %'))->numeric()->default(0),
@@ -51,7 +51,7 @@ class WorksRelationManager extends RelationManager
->options(fn () => User::pluck('name', 'id')) ->options(fn () => User::pluck('name', 'id'))
->searchable(), ->searchable(),
Forms\Components\Select::make('status') Forms\Components\Select::make('status')
->options(WorkOrderWork::STATUSES) ->options(\App\Support\I18n::opts(WorkOrderWork::STATUSES))
->default('todo') ->default('todo')
->required(), ->required(),
Forms\Components\Textarea::make('notes')->label(__('Notițe'))->columnSpanFull()->rows(2), Forms\Components\Textarea::make('notes')->label(__('Notițe'))->columnSpanFull()->rows(2),
@@ -15,7 +15,7 @@ class LowStockTable extends BaseWidget
protected static ?string $heading = null; protected static ?string $heading = null;
public function getHeading(): string protected function getTableHeading(): string
{ {
return '⚠️ ' . __('Stoc minim atins'); return '⚠️ ' . __('Stoc minim atins');
} }
+37 -19
View File
@@ -259,6 +259,7 @@
"Brand": "Brand", "Brand": "Brand",
"Brand & contact": "Brand & contact", "Brand & contact": "Brand & contact",
"Break": "Wagon", "Break": "Wagon",
"Budget": "Budget",
"Buget": "Budget", "Buget": "Budget",
"Buget & rezultate (luna curentă)": "Budget & results (current month)", "Buget & rezultate (luna curentă)": "Budget & results (current month)",
"Bulk actions": "Bulk actions", "Bulk actions": "Bulk actions",
@@ -327,9 +328,9 @@
"Class": "Class", "Class": "Class",
"Clasă (pentru pricing)": "Class (for pricing)", "Clasă (pentru pricing)": "Class (for pricing)",
"Claude API Key": "Claude API Key", "Claude API Key": "Claude API Key",
"Click pentru a redenumi": "Click pentru a redenumi", "Click pentru a redenumi": "Click to rename",
"Client": "Client", "Client": "Client",
"Client & Auto": "Client & Auto", "Client & Auto": "Client & Vehicle",
"Client (nume, semnătură):": "Client (name, signature):", "Client (nume, semnătură):": "Client (name, signature):",
"Client / Auto": "Client / Auto", "Client / Auto": "Client / Auto",
"Client CRM": "CRM client", "Client CRM": "CRM client",
@@ -371,6 +372,7 @@
"Comandat": "Comandat", "Comandat": "Comandat",
"Comandată": "Ordered", "Comandată": "Ordered",
"Comandă": "Order", "Comandă": "Order",
"Comandă emisă": "Order issued",
"Comandă nouă #": "New order #", "Comandă nouă #": "New order #",
"Comandă primită": "Order received", "Comandă primită": "Order received",
"Combustibil": "Fuel", "Combustibil": "Fuel",
@@ -458,6 +460,8 @@
"Culoare brand": "Brand color", "Culoare brand": "Brand color",
"Culoare în calendar": "Color in calendar", "Culoare în calendar": "Color in calendar",
"Cum folosești API-ul:": "How to use the API:", "Cum folosești API-ul:": "How to use the API:",
"Cum funcționează": "How it works",
"Cum funcționează:": "How it works:",
"Cumul.": "Cumul.", "Cumul.": "Cumul.",
"Cumulabil": "Cumulabil", "Cumulabil": "Cumulabil",
"Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.": "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.", "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.": "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.",
@@ -688,7 +692,7 @@
"Filters": "Filters", "Filters": "Filters",
"Filtre": "Filters", "Filtre": "Filters",
"Filtru": "Filter", "Filtru": "Filter",
"Filtru:": "Filtru:", "Filtru:": "Filter:",
"Finalizat": "Done", "Finalizat": "Done",
"Financiar": "Financiar", "Financiar": "Financiar",
"Finanțe": "Finance", "Finanțe": "Finance",
@@ -756,7 +760,7 @@
"Gol — trage un card aici": "Empty — drop a card here", "Gol — trage un card aici": "Empty — drop a card here",
"Grafic": "Chart", "Grafic": "Chart",
"Gravitate": "Gravitate", "Gravitate": "Gravitate",
"Grupare:": "Grupare:", "Grupare:": "Group:",
"Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet", "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet",
"Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.", "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.",
"Găsite (cu articol existent)": "Found (with existing article)", "Găsite (cu articol existent)": "Found (with existing article)",
@@ -898,6 +902,8 @@
"Logout": "Logout", "Logout": "Logout",
"Loturi": "Loturi", "Loturi": "Loturi",
"Loturi (FIFO)": "Loturi (FIFO)", "Loturi (FIFO)": "Loturi (FIFO)",
"Low Stock Table": "Low stock",
"Low stock": "Low stock",
"Lucrare": "Lucrare", "Lucrare": "Lucrare",
"Lucrare blocată": "Work blocked", "Lucrare blocată": "Work blocked",
"Lucrări": "Tasks", "Lucrări": "Tasks",
@@ -908,7 +914,7 @@
"Luna trecută": "Last month", "Luna trecută": "Last month",
"Luna următoare ▶": "Next month ▶", "Luna următoare ▶": "Next month ▶",
"Lunar": "Lunar", "Lunar": "Lunar",
"Luni": "Months", "Luni": "Monday",
"Luni (zi)": "Monday", "Luni (zi)": "Monday",
"Luni Vineri: 08:00 18:00": "Luni Vineri: 08:00 18:00", "Luni Vineri: 08:00 18:00": "Luni Vineri: 08:00 18:00",
"Lună": "Month", "Lună": "Month",
@@ -924,7 +930,7 @@
"Mai": "May", "Mai": "May",
"Mai mic = aplicat primul.": "Mai mic = aplicat primul.", "Mai mic = aplicat primul.": "Mai mic = aplicat primul.",
"Maistru": "Master", "Maistru": "Master",
"Maistru / Mecanic": "Maistru / Mecanic", "Maistru / Mecanic": "Master / Mechanic",
"Maistru / Recepție:": "Master / Reception:", "Maistru / Recepție:": "Master / Reception:",
"Make": "Make", "Make": "Make",
"Manager": "Manager", "Manager": "Manager",
@@ -960,7 +966,7 @@
"Marți": "Tuesday", "Marți": "Tuesday",
"Master": "Master", "Master": "Master",
"Master name": "Master", "Master name": "Master",
"Matricea": "Matricea", "Matricea": "Matrix",
"Max clienți": "Max clients", "Max clienți": "Max clients",
"Max fișe/lună": "Max orders/month", "Max fișe/lună": "Max orders/month",
"Max mașini": "Max vehicles", "Max mașini": "Max vehicles",
@@ -969,6 +975,7 @@
"Mașina e gata de ridicat": "Vehicle ready for pickup", "Mașina e gata de ridicat": "Vehicle ready for pickup",
"Mașini": "Vehicles", "Mașini": "Vehicles",
"Mecanic": "Mechanic", "Mecanic": "Mechanic",
"Mecanic / Zi": "Mechanic / Day",
"Mecanic implicit": "Default mechanic", "Mecanic implicit": "Default mechanic",
"Mecanici": "Mechanics", "Mecanici": "Mechanics",
"Medie": "Medium", "Medie": "Medium",
@@ -995,7 +1002,7 @@
"Mod": "Mode", "Mod": "Mode",
"Mod stub:": "Mod stub:", "Mod stub:": "Mod stub:",
"Mod tarifare": "Mod tarifare", "Mod tarifare": "Mod tarifare",
"Mod:": "Mod:", "Mod:": "Mode:",
"Model": "Model", "Model": "Model",
"Model Claude": "Model Claude", "Model Claude": "Model Claude",
"Model Gemini": "Model Gemini", "Model Gemini": "Model Gemini",
@@ -1029,6 +1036,7 @@
"Neconfirmate": "Unconfirmed", "Neconfirmate": "Unconfirmed",
"Necunoscut": "Unknown", "Necunoscut": "Unknown",
"Neplătit": "Unpaid", "Neplătit": "Unpaid",
"Neprezentat": "No-show",
"Nepublicat": "Unpublished", "Nepublicat": "Unpublished",
"Nesemnat": "Unsigned", "Nesemnat": "Unsigned",
"Nesincronizat": "Not synced", "Nesincronizat": "Not synced",
@@ -1169,7 +1177,7 @@
"Ore (normă)": "Hours (norm)", "Ore (normă)": "Hours (norm)",
"Ore disponibile / zi": "Available hours / day", "Ore disponibile / zi": "Available hours / day",
"Ore lucrate": "Hours worked", "Ore lucrate": "Hours worked",
"Ore programate": "Ore programate", "Ore programate": "Scheduled hours",
"Ore total": "Ore total", "Ore total": "Ore total",
"Ore/zi": "Hours/day", "Ore/zi": "Hours/day",
"Owner": "Owner", "Owner": "Owner",
@@ -1264,7 +1272,9 @@
"Plăți internaționale. Mai potrivit pentru clienți din afara MD.": "Plăți internaționale. Mai potrivit pentru clienți din afara MD.", "Plăți internaționale. Mai potrivit pentru clienți din afara MD.": "Plăți internaționale. Mai potrivit pentru clienți din afara MD.",
"Pod": "Bay", "Pod": "Bay",
"Pod / Spațiu lucru": "Bay / Work space", "Pod / Spațiu lucru": "Bay / Work space",
"Pod / Zi": "Bay / Day",
"Pod / spațiu": "Bay / space", "Pod / spațiu": "Bay / space",
"Pod × Zile": "Bay × Days",
"Politica de confidențialitate": "Privacy policy", "Politica de confidențialitate": "Privacy policy",
"Politici": "Policies", "Politici": "Policies",
"Pontaj": "Timesheet", "Pontaj": "Timesheet",
@@ -1397,6 +1407,8 @@
"Recepționat": "Received", "Recepționat": "Received",
"Recepționat — batch creat": "Recepționat — batch creat", "Recepționat — batch creat": "Recepționat — batch creat",
"Recepționată": "Received", "Recepționată": "Received",
"Recepționată parțial": "Partially received",
"Recepționată total": "Fully received",
"Recepționează": "Receive", "Recepționează": "Receive",
"Recomandat": "Recommended", "Recomandat": "Recommended",
"Recomandate": "Recommended", "Recomandate": "Recommended",
@@ -1637,7 +1649,7 @@
"Suspensie": "Suspension", "Suspensie": "Suspension",
"Sâmbătă": "Saturday", "Sâmbătă": "Saturday",
"Sâmbătă: 09:00 14:00": "Sâmbătă: 09:00 14:00", "Sâmbătă: 09:00 14:00": "Sâmbătă: 09:00 14:00",
"Săpt": "Săpt", "Săpt": "Week",
"Săpt. lucrătoare": "Working days", "Săpt. lucrătoare": "Working days",
"Săpt. următoare →": "Săpt. următoare →", "Săpt. următoare →": "Săpt. următoare →",
"Săptămâna aceasta": "This week", "Săptămâna aceasta": "This week",
@@ -1744,9 +1756,10 @@
"Total în baza de date": "Total in database", "Total în baza de date": "Total in database",
"Total încasat": "Total încasat", "Total încasat": "Total încasat",
"Total înregistrate": "Total registered", "Total înregistrate": "Total registered",
"Toți": "All",
"Toți VIP-ii sunt în contact recent.": "Toți VIP-ii sunt în contact recent.", "Toți VIP-ii sunt în contact recent.": "Toți VIP-ii sunt în contact recent.",
"Toți clienții": "All clients", "Toți clienții": "All clients",
"Toți mecanicii": "Toți mecanicii", "Toți mecanicii": "All mechanics",
"Toți utilizatorii": "All users", "Toți utilizatorii": "All users",
"Tracking & ETA": "Tracking & ETA", "Tracking & ETA": "Tracking & ETA",
"Tracțiune": "Drive", "Tracțiune": "Drive",
@@ -1827,7 +1840,7 @@
"Vehicle class": "Vehicle class", "Vehicle class": "Vehicle class",
"Vehicle make": "Vehicle make", "Vehicle make": "Vehicle make",
"Vehicle model": "Vehicle model", "Vehicle model": "Vehicle model",
"Vehicle plate": "Vehicle plate", "Vehicle plate": "Plate",
"Vehicul": "Vehicle", "Vehicul": "Vehicle",
"Vehicul existent": "Existing vehicle", "Vehicul existent": "Existing vehicle",
"Vehicul nou": "New vehicle", "Vehicul nou": "New vehicle",
@@ -1887,7 +1900,7 @@
"Yes": "Yes", "Yes": "Yes",
"ZIP": "ZIP", "ZIP": "ZIP",
"ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.": "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.", "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.": "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.",
"Zi": "Zi", "Zi": "Day",
"Zile": "Days", "Zile": "Days",
"Zile libere": "Days off", "Zile libere": "Days off",
"Zile livrare": "Zile livrare", "Zile livrare": "Zile livrare",
@@ -1914,6 +1927,7 @@
"call": "Call", "call": "Call",
"canal": "channel", "canal": "channel",
"canale marketing": "canale marketing", "canale marketing": "canale marketing",
"capacitate": "capacity",
"cerere": "lead", "cerere": "lead",
"cereri": "leads", "cereri": "leads",
"cheltuială": "cheltuială", "cheltuială": "cheltuială",
@@ -1958,7 +1972,7 @@
"instagram": "Instagram", "instagram": "Instagram",
"jurnal": "log", "jurnal": "log",
"la fiecare request": "la fiecare request", "la fiecare request": "la fiecare request",
"liber/ușor": "liber/ușor", "liber/ușor": "free/light",
"linii neîncasate.": "linii neîncasate.", "linii neîncasate.": "linii neîncasate.",
"lucrare caroserie": "bodyshop job", "lucrare caroserie": "bodyshop job",
"lucrare terți": "subcontract job", "lucrare terți": "subcontract job",
@@ -1966,6 +1980,7 @@
"lucrări terți": "subcontract jobs", "lucrări terți": "subcontract jobs",
"mașini": "vehicles", "mașini": "vehicles",
"mașină": "vehicle", "mașină": "vehicle",
"mediu": "medium",
"mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).": "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).", "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).": "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).",
"new": "new", "new": "new",
"niciodată": "niciodată", "niciodată": "niciodată",
@@ -1980,6 +1995,7 @@
"plan": "plan", "plan": "plan",
"planuri": "planuri", "planuri": "planuri",
"plată": "plată", "plată": "plată",
"plin": "full",
"plăți": "plăți", "plăți": "plăți",
"pod": "bay", "pod": "bay",
"portal.common.currency_mdl": "portal.common.currency_mdl", "portal.common.currency_mdl": "portal.common.currency_mdl",
@@ -2098,8 +2114,9 @@
"posturi de lucru": "posturi de lucru", "posturi de lucru": "posturi de lucru",
"programare": "appointment", "programare": "appointment",
"programări": "appointments", "programări": "appointments",
"programări active": "programări active", "programări active": "active appointments",
"programări neconfirmate &lt; 24h": "programări neconfirmate &lt; 24h", "programări neconfirmate &lt; 24h": "unconfirmed appointments < 24h",
"rata confirmare": "confirmation rate",
"referral": "Referral", "referral": "Referral",
"reguli markup": "reguli markup", "reguli markup": "reguli markup",
"regulă": "regulă", "regulă": "regulă",
@@ -2113,6 +2130,7 @@
"site": "Website", "site": "Website",
"subcontractor": "subcontractor", "subcontractor": "subcontractor",
"subcontractori": "subcontractors", "subcontractori": "subcontractors",
"săptămâna curentă": "current week",
"tehnician": "technician", "tehnician": "technician",
"tehnicieni": "technicians", "tehnicieni": "technicians",
"telegram": "Telegram", "telegram": "Telegram",
@@ -2149,11 +2167,11 @@
"Închide": "Close", "Închide": "Close",
"Închide fișa": "Close order", "Închide fișa": "Close order",
"Închis": "Closed", "Închis": "Closed",
"Închis (Duminică/sărbătoare)": "Închis (Duminică/sărbătoare)", "Închis (Duminică/sărbătoare)": "Closed (Sunday/holiday)",
"Închis la": "Closed at", "Închis la": "Closed at",
"Închise azi": "Closed today", "Închise azi": "Closed today",
"Încărcare STO": "Workshop load", "Încărcare STO": "Workshop load",
"Încărcare celulă": "Încărcare celulă", "Încărcare celulă": "Cell load",
"Încărcare service": "Workshop load", "Încărcare service": "Workshop load",
"Înregistrare": "Register", "Înregistrare": "Register",
"Înregistrat": "Registered", "Înregistrat": "Registered",
@@ -2199,7 +2217,7 @@
"◀ Luna precedentă": "◀ Previous month", "◀ Luna precedentă": "◀ Previous month",
"⚖️ Balanță": "⚖️ Balanță", "⚖️ Balanță": "⚖️ Balanță",
"⚙ Configurare tenant": "⚙ Configurare tenant", "⚙ Configurare tenant": "⚙ Configurare tenant",
"⚙ Cum funcționează:": "⚙ Cum funcționează:", "⚙ Cum funcționează:": "⚙ How it works:",
"⚠ Acțiune necesară": "⚠ Action needed", "⚠ Acțiune necesară": "⚠ Action needed",
"⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.": "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.", "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.": "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.",
"⚠ Fără plan": "⚠ Fără plan", "⚠ Fără plan": "⚠ Fără plan",
+40 -22
View File
@@ -250,7 +250,7 @@
"Blochez": "Блокировать", "Blochez": "Блокировать",
"Blochez lucrarea": "Заблокировать работу", "Blochez lucrarea": "Заблокировать работу",
"Boală": "Больничный", "Boală": "Больничный",
"Body type": "Кузов", "Body type": "Тип кузова",
"Bon": "Чек", "Bon": "Чек",
"Bonuri": "Чеки", "Bonuri": "Чеки",
"Bot OK: @{$name}": "Bot OK: @{$name}", "Bot OK: @{$name}": "Bot OK: @{$name}",
@@ -259,6 +259,7 @@
"Brand": "Бренд", "Brand": "Бренд",
"Brand & contact": "Бренд и контакты", "Brand & contact": "Бренд и контакты",
"Break": "Универсал", "Break": "Универсал",
"Budget": "Бюджет",
"Buget": "Бюджет", "Buget": "Бюджет",
"Buget & rezultate (luna curentă)": "Бюджет и результаты (текущий месяц)", "Buget & rezultate (luna curentă)": "Бюджет и результаты (текущий месяц)",
"Bulk actions": "Массовые действия", "Bulk actions": "Массовые действия",
@@ -327,9 +328,9 @@
"Class": "Класс", "Class": "Класс",
"Clasă (pentru pricing)": "Класс (для тарификации)", "Clasă (pentru pricing)": "Класс (для тарификации)",
"Claude API Key": "Claude API Key", "Claude API Key": "Claude API Key",
"Click pentru a redenumi": "Click pentru a redenumi", "Click pentru a redenumi": "Кликните для переименования",
"Client": "Клиент", "Client": "Клиент",
"Client & Auto": "Client & Auto", "Client & Auto": "Клиент и авто",
"Client (nume, semnătură):": "Клиент (имя, подпись):", "Client (nume, semnătură):": "Клиент (имя, подпись):",
"Client / Auto": "Client / Auto", "Client / Auto": "Client / Auto",
"Client CRM": "Клиент CRM", "Client CRM": "Клиент CRM",
@@ -371,6 +372,7 @@
"Comandat": "Comandat", "Comandat": "Comandat",
"Comandată": "Заказана", "Comandată": "Заказана",
"Comandă": "Заказ", "Comandă": "Заказ",
"Comandă emisă": "Заказ создан",
"Comandă nouă #": "Новый заказ #", "Comandă nouă #": "Новый заказ #",
"Comandă primită": "Заказ получен", "Comandă primită": "Заказ получен",
"Combustibil": "Топливо", "Combustibil": "Топливо",
@@ -458,6 +460,8 @@
"Culoare brand": "Цвет бренда", "Culoare brand": "Цвет бренда",
"Culoare în calendar": "Цвет в календаре", "Culoare în calendar": "Цвет в календаре",
"Cum folosești API-ul:": "Как использовать API:", "Cum folosești API-ul:": "Как использовать API:",
"Cum funcționează": "Как работает",
"Cum funcționează:": "Как работает:",
"Cumul.": "Cumul.", "Cumul.": "Cumul.",
"Cumulabil": "Cumulabil", "Cumulabil": "Cumulabil",
"Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.": "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.", "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.": "Cumulabil = se înmulțește cu alți coeficienți. Necumulabil = doar cel mai mare necumulabil se aplică.",
@@ -688,7 +692,7 @@
"Filters": "Фильтры", "Filters": "Фильтры",
"Filtre": "Фильтры", "Filtre": "Фильтры",
"Filtru": "Фильтр", "Filtru": "Фильтр",
"Filtru:": "Filtru:", "Filtru:": "Фильтр:",
"Finalizat": "Завершено", "Finalizat": "Завершено",
"Financiar": "Financiar", "Financiar": "Financiar",
"Finanțe": "Финансы", "Finanțe": "Финансы",
@@ -756,7 +760,7 @@
"Gol — trage un card aici": "Пусто — перетащите карточку сюда", "Gol — trage un card aici": "Пусто — перетащите карточку сюда",
"Grafic": "График", "Grafic": "График",
"Gravitate": "Gravitate", "Gravitate": "Gravitate",
"Grupare:": "Grupare:", "Grupare:": "Группировка:",
"Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet", "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet",
"Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.", "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.": "Grupează manopere + piese frecvente într-un șablon (ex: „Schimb ulei complet\") și aplică-l pe o fișă cu un click.",
"Găsite (cu articol existent)": "Найдено (с существующим артикулом)", "Găsite (cu articol existent)": "Найдено (с существующим артикулом)",
@@ -898,6 +902,8 @@
"Logout": "Выход", "Logout": "Выход",
"Loturi": "Loturi", "Loturi": "Loturi",
"Loturi (FIFO)": "Loturi (FIFO)", "Loturi (FIFO)": "Loturi (FIFO)",
"Low Stock Table": "Остаток ниже минимума",
"Low stock": "Ниже минимума",
"Lucrare": "Lucrare", "Lucrare": "Lucrare",
"Lucrare blocată": "Работа заблокирована", "Lucrare blocată": "Работа заблокирована",
"Lucrări": "Работы", "Lucrări": "Работы",
@@ -908,7 +914,7 @@
"Luna trecută": "Прошлый месяц", "Luna trecută": "Прошлый месяц",
"Luna următoare ▶": "Следующий месяц ▶", "Luna următoare ▶": "Следующий месяц ▶",
"Lunar": "Lunar", "Lunar": "Lunar",
"Luni": "Месяцы", "Luni": "Понедельник",
"Luni (zi)": "Понедельник", "Luni (zi)": "Понедельник",
"Luni Vineri: 08:00 18:00": "Luni Vineri: 08:00 18:00", "Luni Vineri: 08:00 18:00": "Luni Vineri: 08:00 18:00",
"Lună": "Месяц", "Lună": "Месяц",
@@ -924,7 +930,7 @@
"Mai": "Май", "Mai": "Май",
"Mai mic = aplicat primul.": "Mai mic = aplicat primul.", "Mai mic = aplicat primul.": "Mai mic = aplicat primul.",
"Maistru": "Мастер", "Maistru": "Мастер",
"Maistru / Mecanic": "Maistru / Mecanic", "Maistru / Mecanic": "Мастер / Механик",
"Maistru / Recepție:": "Мастер / Ресепшн:", "Maistru / Recepție:": "Мастер / Ресепшн:",
"Make": "Марка", "Make": "Марка",
"Manager": "Менеджер", "Manager": "Менеджер",
@@ -960,7 +966,7 @@
"Marți": "Вторник", "Marți": "Вторник",
"Master": "Мастер", "Master": "Мастер",
"Master name": "Мастер", "Master name": "Мастер",
"Matricea": "Matricea", "Matricea": "Матрица",
"Max clienți": "Макс. клиентов", "Max clienți": "Макс. клиентов",
"Max fișe/lună": "Макс. нарядов/мес", "Max fișe/lună": "Макс. нарядов/мес",
"Max mașini": "Макс. авто", "Max mașini": "Макс. авто",
@@ -969,6 +975,7 @@
"Mașina e gata de ridicat": "Авто готово к выдаче", "Mașina e gata de ridicat": "Авто готово к выдаче",
"Mașini": "Автомобили", "Mașini": "Автомобили",
"Mecanic": "Механик", "Mecanic": "Механик",
"Mecanic / Zi": "Механик / День",
"Mecanic implicit": "Механик по умолчанию", "Mecanic implicit": "Механик по умолчанию",
"Mecanici": "Механики", "Mecanici": "Механики",
"Medie": "Среднее", "Medie": "Среднее",
@@ -995,7 +1002,7 @@
"Mod": "Режим", "Mod": "Режим",
"Mod stub:": "Mod stub:", "Mod stub:": "Mod stub:",
"Mod tarifare": "Mod tarifare", "Mod tarifare": "Mod tarifare",
"Mod:": "Mod:", "Mod:": "Режим:",
"Model": "Модель", "Model": "Модель",
"Model Claude": "Model Claude", "Model Claude": "Model Claude",
"Model Gemini": "Model Gemini", "Model Gemini": "Model Gemini",
@@ -1029,6 +1036,7 @@
"Neconfirmate": "Не подтверждено", "Neconfirmate": "Не подтверждено",
"Necunoscut": "Неизвестно", "Necunoscut": "Неизвестно",
"Neplătit": "Не оплачено", "Neplătit": "Не оплачено",
"Neprezentat": "Не явился",
"Nepublicat": "Не опубликовано", "Nepublicat": "Не опубликовано",
"Nesemnat": "Не подписано", "Nesemnat": "Не подписано",
"Nesincronizat": "Не синхронизировано", "Nesincronizat": "Не синхронизировано",
@@ -1077,7 +1085,7 @@
"Niciun tenant încă": "Пока нет арендаторов", "Niciun tenant încă": "Пока нет арендаторов",
"Niciun șablon": "Нет шаблонов", "Niciun șablon": "Нет шаблонов",
"No": "Нет", "No": "Нет",
"No-show alert": "No-show alert", "No-show alert": "No-show предупр.",
"Noiembrie": "Ноябрь", "Noiembrie": "Ноябрь",
"Norm hours": "Норма часов", "Norm hours": "Норма часов",
"Norma ore": "Норма часов", "Norma ore": "Норма часов",
@@ -1169,7 +1177,7 @@
"Ore (normă)": "Часы (норма)", "Ore (normă)": "Часы (норма)",
"Ore disponibile / zi": "Доступные часы / день", "Ore disponibile / zi": "Доступные часы / день",
"Ore lucrate": "Отработанные часы", "Ore lucrate": "Отработанные часы",
"Ore programate": "Ore programate", "Ore programate": "Запланированные часы",
"Ore total": "Ore total", "Ore total": "Ore total",
"Ore/zi": "Часов/день", "Ore/zi": "Часов/день",
"Owner": "Владелец", "Owner": "Владелец",
@@ -1264,7 +1272,9 @@
"Plăți internaționale. Mai potrivit pentru clienți din afara MD.": "Plăți internaționale. Mai potrivit pentru clienți din afara MD.", "Plăți internaționale. Mai potrivit pentru clienți din afara MD.": "Plăți internaționale. Mai potrivit pentru clienți din afara MD.",
"Pod": "Пост", "Pod": "Пост",
"Pod / Spațiu lucru": "Пост / рабочее место", "Pod / Spațiu lucru": "Пост / рабочее место",
"Pod / Zi": "Пост / День",
"Pod / spațiu": "Пост / место", "Pod / spațiu": "Пост / место",
"Pod × Zile": "Пост × Дни",
"Politica de confidențialitate": "Политика конфиденциальности", "Politica de confidențialitate": "Политика конфиденциальности",
"Politici": "Политики", "Politici": "Политики",
"Pontaj": "Табель", "Pontaj": "Табель",
@@ -1397,6 +1407,8 @@
"Recepționat": "Принято", "Recepționat": "Принято",
"Recepționat — batch creat": "Recepționat — batch creat", "Recepționat — batch creat": "Recepționat — batch creat",
"Recepționată": "Принято", "Recepționată": "Принято",
"Recepționată parțial": "Частично принято",
"Recepționată total": "Полностью принято",
"Recepționează": "Принять", "Recepționează": "Принять",
"Recomandat": "Рекомендуется", "Recomandat": "Рекомендуется",
"Recomandate": "Рекомендуемые", "Recomandate": "Рекомендуемые",
@@ -1637,7 +1649,7 @@
"Suspensie": "Подвеска", "Suspensie": "Подвеска",
"Sâmbătă": "Суббота", "Sâmbătă": "Суббота",
"Sâmbătă: 09:00 14:00": "Sâmbătă: 09:00 14:00", "Sâmbătă: 09:00 14:00": "Sâmbătă: 09:00 14:00",
"Săpt": "Săpt", "Săpt": "Нед",
"Săpt. lucrătoare": "Раб. дни", "Săpt. lucrătoare": "Раб. дни",
"Săpt. următoare →": "Săpt. următoare →", "Săpt. următoare →": "Săpt. următoare →",
"Săptămâna aceasta": "На этой неделе", "Săptămâna aceasta": "На этой неделе",
@@ -1744,9 +1756,10 @@
"Total în baza de date": "Всего в базе", "Total în baza de date": "Всего в базе",
"Total încasat": "Total încasat", "Total încasat": "Total încasat",
"Total înregistrate": "Всего зарегистрировано", "Total înregistrate": "Всего зарегистрировано",
"Toți": "Все",
"Toți VIP-ii sunt în contact recent.": "Toți VIP-ii sunt în contact recent.", "Toți VIP-ii sunt în contact recent.": "Toți VIP-ii sunt în contact recent.",
"Toți clienții": "Все клиенты", "Toți clienții": "Все клиенты",
"Toți mecanicii": "Toți mecanicii", "Toți mecanicii": "Все механики",
"Toți utilizatorii": "Все пользователи", "Toți utilizatorii": "Все пользователи",
"Tracking & ETA": "Отслеживание и ETA", "Tracking & ETA": "Отслеживание и ETA",
"Tracțiune": "Привод", "Tracțiune": "Привод",
@@ -1827,7 +1840,7 @@
"Vehicle class": "Класс авто", "Vehicle class": "Класс авто",
"Vehicle make": "Марка авто", "Vehicle make": "Марка авто",
"Vehicle model": "Модель авто", "Vehicle model": "Модель авто",
"Vehicle plate": "Гос. номер авто", "Vehicle plate": "Гос. номер",
"Vehicul": "Транспорт", "Vehicul": "Транспорт",
"Vehicul existent": "Существующий транспорт", "Vehicul existent": "Существующий транспорт",
"Vehicul nou": "Новый транспорт", "Vehicul nou": "Новый транспорт",
@@ -1887,7 +1900,7 @@
"Yes": "Да", "Yes": "Да",
"ZIP": "ZIP", "ZIP": "ZIP",
"ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.": "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.", "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.": "ZIP cu fișiere JSON (1 per tabel) + media + manifest.json.",
"Zi": "Zi", "Zi": "День",
"Zile": "Дни", "Zile": "Дни",
"Zile libere": "Выходные", "Zile libere": "Выходные",
"Zile livrare": "Zile livrare", "Zile livrare": "Zile livrare",
@@ -1914,6 +1927,7 @@
"call": "Звонок", "call": "Звонок",
"canal": "канал", "canal": "канал",
"canale marketing": "canale marketing", "canale marketing": "canale marketing",
"capacitate": "загрузка",
"cerere": "заявка", "cerere": "заявка",
"cereri": "заявки", "cereri": "заявки",
"cheltuială": "cheltuială", "cheltuială": "cheltuială",
@@ -1958,7 +1972,7 @@
"instagram": "Instagram", "instagram": "Instagram",
"jurnal": "журнал", "jurnal": "журнал",
"la fiecare request": "la fiecare request", "la fiecare request": "la fiecare request",
"liber/ușor": "liber/ușor", "liber/ușor": "свободно/легко",
"linii neîncasate.": "linii neîncasate.", "linii neîncasate.": "linii neîncasate.",
"lucrare caroserie": "кузовная работа", "lucrare caroserie": "кузовная работа",
"lucrare terți": "работа субподрядчика", "lucrare terți": "работа субподрядчика",
@@ -1966,6 +1980,7 @@
"lucrări terți": "работы субподрядчиков", "lucrări terți": "работы субподрядчиков",
"mașini": "машины", "mașini": "машины",
"mașină": "машина", "mașină": "машина",
"mediu": "средняя",
"mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).": "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).", "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).": "mergi la Setări → Asistent AI și adaugă cheia API (Claude / GPT / Gemini).",
"new": "новый", "new": "новый",
"niciodată": "niciodată", "niciodată": "niciodată",
@@ -1980,6 +1995,7 @@
"plan": "plan", "plan": "plan",
"planuri": "planuri", "planuri": "planuri",
"plată": "plată", "plată": "plată",
"plin": "полная",
"plăți": "plăți", "plăți": "plăți",
"pod": "пост", "pod": "пост",
"portal.common.currency_mdl": "portal.common.currency_mdl", "portal.common.currency_mdl": "portal.common.currency_mdl",
@@ -2098,8 +2114,9 @@
"posturi de lucru": "posturi de lucru", "posturi de lucru": "posturi de lucru",
"programare": "запись", "programare": "запись",
"programări": "записи", "programări": "записи",
"programări active": "programări active", "programări active": "активные записи",
"programări neconfirmate &lt; 24h": "programări neconfirmate &lt; 24h", "programări neconfirmate &lt; 24h": "неподтверждённые записи < 24ч",
"rata confirmare": "коэф. подтверждения",
"referral": "Рекомендация", "referral": "Рекомендация",
"reguli markup": "reguli markup", "reguli markup": "reguli markup",
"regulă": "regulă", "regulă": "regulă",
@@ -2113,6 +2130,7 @@
"site": "Сайт", "site": "Сайт",
"subcontractor": "субподрядчик", "subcontractor": "субподрядчик",
"subcontractori": "субподрядчики", "subcontractori": "субподрядчики",
"săptămâna curentă": "текущая неделя",
"tehnician": "техник", "tehnician": "техник",
"tehnicieni": "техники", "tehnicieni": "техники",
"telegram": "Telegram", "telegram": "Telegram",
@@ -2149,11 +2167,11 @@
"Închide": "Закрыть", "Închide": "Закрыть",
"Închide fișa": "Закрыть наряд", "Închide fișa": "Закрыть наряд",
"Închis": "Закрыт", "Închis": "Закрыт",
"Închis (Duminică/sărbătoare)": "Închis (Duminică/sărbătoare)", "Închis (Duminică/sărbătoare)": "Закрыто (Воскр./праздник)",
"Închis la": "Закрыт", "Închis la": "Закрыт",
"Închise azi": "Закрыто сегодня", "Închise azi": "Закрыто сегодня",
"Încărcare STO": "Загрузка СТО", "Încărcare STO": "Загрузка СТО",
"Încărcare celulă": "Încărcare celulă", "Încărcare celulă": "Загрузка ячейки",
"Încărcare service": "Загрузка сервиса", "Încărcare service": "Загрузка сервиса",
"Înregistrare": "Регистрация", "Înregistrare": "Регистрация",
"Înregistrat": "Зарегистрирован", "Înregistrat": "Зарегистрирован",
@@ -2193,13 +2211,13 @@
"↗ Deschide Purchase": "↗ Deschide Purchase", "↗ Deschide Purchase": "↗ Deschide Purchase",
"↗ Deschide comanda în Filament": "↗ Deschide comanda în Filament", "↗ Deschide comanda în Filament": "↗ Deschide comanda în Filament",
"↗ Editare": "↗ Editare", "↗ Editare": "↗ Editare",
"≥9h/10": "≥9h/10", "≥9h/10": "≥9ч/10",
"⏰ Abonament expirat": "⏰ Abonament expirat", "⏰ Abonament expirat": "⏰ Abonament expirat",
"⏹ Oprește": "⏹ Oprește", "⏹ Oprește": "⏹ Oprește",
"◀ Luna precedentă": "◀ Предыдущий месяц", "◀ Luna precedentă": "◀ Предыдущий месяц",
"⚖️ Balanță": "⚖️ Balanță", "⚖️ Balanță": "⚖️ Balanță",
"⚙ Configurare tenant": "⚙ Configurare tenant", "⚙ Configurare tenant": "⚙ Configurare tenant",
"⚙ Cum funcționează:": "⚙ Cum funcționează:", "⚙ Cum funcționează:": "⚙ Как работает:",
"⚠ Acțiune necesară": "⚠ Требуется действие", "⚠ Acțiune necesară": "⚠ Требуется действие",
"⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.": "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.", "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.": "⚠ Backup-urile pot conține date sensibile (telefoane, emailuri, plăți). Stochează-le în siguranță.",
"⚠ Fără plan": "⚠ Fără plan", "⚠ Fără plan": "⚠ Fără plan",
@@ -169,7 +169,7 @@
<div class="cv-kpi"> <div class="cv-kpi">
<div class="cv-kpi-label">{{ __('Ore programate') }}</div> <div class="cv-kpi-label">{{ __('Ore programate') }}</div>
<div class="cv-kpi-value">{{ $stats['scheduled_hours'] }} / {{ $stats['capacity_hours'] }}</div> <div class="cv-kpi-value">{{ $stats['scheduled_hours'] }} / {{ $stats['capacity_hours'] }}</div>
<div class="cv-kpi-sub">săptămâna curentă · {{ $stats['utilization_pct'] }}% capacitate</div> <div class="cv-kpi-sub">{{ __('săptămâna curentă') }} · {{ $stats['utilization_pct'] }}% {{ __('capacitate') }}</div>
</div> </div>
<div class="cv-kpi"> <div class="cv-kpi">
<div class="cv-kpi-label">{{ __('Fișe deschise') }}</div> <div class="cv-kpi-label">{{ __('Fișe deschise') }}</div>
@@ -179,7 +179,7 @@
<div class="cv-kpi"> <div class="cv-kpi">
<div class="cv-kpi-label">{{ __('Confirmate') }}</div> <div class="cv-kpi-label">{{ __('Confirmate') }}</div>
<div class="cv-kpi-value green">{{ $stats['confirmed_count'] }} / {{ $stats['total_count'] }}</div> <div class="cv-kpi-value green">{{ $stats['confirmed_count'] }} / {{ $stats['total_count'] }}</div>
<div class="cv-kpi-sub">{{ $stats['confirmation_rate_pct'] }}% rata confirmare</div> <div class="cv-kpi-sub">{{ $stats['confirmation_rate_pct'] }}% {{ __('rata confirmare') }}</div>
</div> </div>
<div class="cv-kpi"> <div class="cv-kpi">
<div class="cv-kpi-label">{{ __('No-show alert') }}</div> <div class="cv-kpi-label">{{ __('No-show alert') }}</div>
@@ -277,7 +277,7 @@
@else @else
<div class="cv-matrix-wrap"> <div class="cv-matrix-wrap">
<div class="cv-grid" style="grid-template-columns: 140px repeat({{ count($days) }}, minmax({{ $viewMode === 'month' ? '70' : '160' }}px, 1fr)); min-width: {{ 140 + count($days) * ($viewMode === 'month' ? 75 : 165) }}px;"> <div class="cv-grid" style="grid-template-columns: 140px repeat({{ count($days) }}, minmax({{ $viewMode === 'month' ? '70' : '160' }}px, 1fr)); min-width: {{ 140 + count($days) * ($viewMode === 'month' ? 75 : 165) }}px;">
<div class="cv-cell cv-header-cell" style="background:#EDF2F7;">{{ $groupBy === 'post' ? 'Pod / Zi' : 'Mecanic / Zi' }}</div> <div class="cv-cell cv-header-cell" style="background:#EDF2F7;">{{ $groupBy === 'post' ? __('Pod / Zi') : __('Mecanic / Zi') }}</div>
@foreach ($days as $day) @foreach ($days as $day)
<div class="cv-cell cv-header-cell {{ $day['is_today'] ? 'today' : '' }} {{ $day['is_closed'] ? 'closed' : '' }}"> <div class="cv-cell cv-header-cell {{ $day['is_today'] ? 'today' : '' }} {{ $day['is_closed'] ? 'closed' : '' }}">
<span class="cv-day-name">{{ $day['name'] }}</span> <span class="cv-day-name">{{ $day['name'] }}</span>
@@ -354,8 +354,8 @@
<div class="cv-legend-col">{{ __('Încărcare celulă') }}</div> <div class="cv-legend-col">{{ __('Încărcare celulă') }}</div>
<div class="cv-legend-items"> <div class="cv-legend-items">
<div class="cv-legend-item"><span class="cv-load" style="position:static;">05h/10</span> {{ __('liber/ușor') }}</div> <div class="cv-legend-item"><span class="cv-load" style="position:static;">05h/10</span> {{ __('liber/ușor') }}</div>
<div class="cv-legend-item"><span class="cv-load warn" style="position:static;">58.5h/10</span> mediu</div> <div class="cv-legend-item"><span class="cv-load warn" style="position:static;">58.5h/10</span> {{ __('mediu') }}</div>
<div class="cv-legend-item"><span class="cv-load full" style="position:static;">{{ __('≥9h/10') }}</span> plin</div> <div class="cv-legend-item"><span class="cv-load full" style="position:static;">{{ __('≥9h/10') }}</span> {{ __('plin') }}</div>
</div> </div>
</div> </div>
<div> <div>