Fix supplier settings page and nominativi legacy query
This commit is contained in:
parent
887540c5fe
commit
f300654479
|
|
@ -372,11 +372,13 @@ protected function getTableQuery(): Builder
|
|||
return $this->buildDomainFallbackQuery((int) $activeStabileId);
|
||||
}
|
||||
|
||||
$legacyTable = 'vw_legacy_condomin_nominativi';
|
||||
|
||||
$base = LegacyCondominNominativo::query()
|
||||
->where('cod_stabile', $codStabile)
|
||||
->where($legacyTable . '.cod_stabile', $codStabile)
|
||||
->where(function (Builder $q): void {
|
||||
$q->whereRaw("TRIM(COALESCE(nom_cond, '')) <> ''")
|
||||
->orWhereRaw("TRIM(COALESCE(inquil_nome, '')) <> ''");
|
||||
$q->whereRaw("TRIM(COALESCE(vw_legacy_condomin_nominativi.nom_cond, '')) <> ''")
|
||||
->orWhereRaw("TRIM(COALESCE(vw_legacy_condomin_nominativi.inquil_nome, '')) <> ''");
|
||||
});
|
||||
|
||||
$latestPerUnit = DB::connection('gescon_import')
|
||||
|
|
@ -393,13 +395,13 @@ protected function getTableQuery(): Builder
|
|||
->on('mx.interno', '=', 'vw_legacy_condomin_nominativi.interno')
|
||||
->on('mx.legacy_year', '=', 'vw_legacy_condomin_nominativi.legacy_year');
|
||||
})
|
||||
->orderBy('scala')
|
||||
->orderBy($legacyTable . '.scala')
|
||||
// Ordine richiesto: per interno (con fallback robusto)
|
||||
->orderByRaw("CASE WHEN interno IS NULL OR interno = '' THEN 1 ELSE 0 END")
|
||||
->orderByRaw("CASE WHEN interno REGEXP '^[0-9]+' THEN CAST(interno AS UNSIGNED) ELSE 999999 END")
|
||||
->orderBy('interno')
|
||||
->orderBy('cod_cond')
|
||||
->orderBy('id');
|
||||
->orderByRaw("CASE WHEN vw_legacy_condomin_nominativi.interno IS NULL OR vw_legacy_condomin_nominativi.interno = '' THEN 1 ELSE 0 END")
|
||||
->orderByRaw("CASE WHEN vw_legacy_condomin_nominativi.interno REGEXP '^[0-9]+' THEN CAST(vw_legacy_condomin_nominativi.interno AS UNSIGNED) ELSE 999999 END")
|
||||
->orderBy($legacyTable . '.interno')
|
||||
->orderBy($legacyTable . '.cod_cond')
|
||||
->orderBy($legacyTable . '.id');
|
||||
}
|
||||
|
||||
protected function hasLegacyNominativiForStabile(string $codStabile): bool
|
||||
|
|
@ -566,6 +568,7 @@ public function table(Table $table): Table
|
|||
{
|
||||
$user = Auth::user();
|
||||
$activeStabileId = $user instanceof User ? (int) (StabileContext::resolveActiveStabileId($user) ?: 0): 0;
|
||||
$legacyTable = 'vw_legacy_condomin_nominativi';
|
||||
|
||||
$codStabile = $activeStabileId > 0
|
||||
? $this->resolveLegacyStabileCode((int) $activeStabileId)
|
||||
|
|
@ -611,7 +614,7 @@ public function table(Table $table): Table
|
|||
return $query;
|
||||
}
|
||||
|
||||
return $query->where('legacy_year', $data['value']);
|
||||
return $query->where($table . '.legacy_year', $data['value']);
|
||||
}),
|
||||
SelectFilter::make('scala')
|
||||
->label('Scala')
|
||||
|
|
@ -646,6 +649,18 @@ public function table(Table $table): Table
|
|||
->pluck('scala', 'scala')
|
||||
->all();
|
||||
})
|
||||
->query(function (Builder $query, array $data) use ($legacyTable): Builder {
|
||||
if (! isset($data['value']) || $data['value'] === '') {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->where($legacyTable . '.scala', $data['value']);
|
||||
}
|
||||
|
||||
return $query->where('scala', $data['value']);
|
||||
})
|
||||
->searchable(),
|
||||
|
||||
SelectFilter::make('piano')
|
||||
|
|
@ -719,12 +734,33 @@ public function table(Table $table): Table
|
|||
|
||||
TextColumn::make('scala')
|
||||
->label('Sc.')
|
||||
->sortable(),
|
||||
->sortable(query: function (Builder $query, string $direction) use ($legacyTable): Builder {
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->orderBy($legacyTable . '.scala', $direction);
|
||||
}
|
||||
|
||||
return $query->orderBy('scala', $direction);
|
||||
}),
|
||||
|
||||
TextColumn::make('interno')
|
||||
->label('Int.')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
->sortable(query: function (Builder $query, string $direction) use ($legacyTable): Builder {
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->orderBy($legacyTable . '.interno', $direction);
|
||||
}
|
||||
|
||||
return $query->orderBy('interno', $direction);
|
||||
})
|
||||
->searchable(query: function (Builder $query, string $search) use ($activeStabileId, $legacyTable): Builder {
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->where($legacyTable . '.interno', 'like', '%' . $search . '%');
|
||||
}
|
||||
|
||||
return $this->applyDomainNominativiSearch($query, $search, $activeStabileId);
|
||||
}),
|
||||
|
||||
TextColumn::make('nom_cond')
|
||||
->label('Condomino')
|
||||
|
|
@ -732,10 +768,10 @@ public function table(Table $table): Table
|
|||
$titolo = $this->resolveTitoloOwnerForRow($record);
|
||||
return $this->formatLegacyDenominazione($titolo, $record->nom_cond ?? (string) $state);
|
||||
})
|
||||
->searchable(query: function (Builder $query, string $search) use ($activeStabileId): Builder {
|
||||
->searchable(query: function (Builder $query, string $search) use ($activeStabileId, $legacyTable): Builder {
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->where('nom_cond', 'like', '%' . $search . '%');
|
||||
return $query->where($legacyTable . '.nom_cond', 'like', '%' . $search . '%');
|
||||
}
|
||||
|
||||
return $this->applyDomainNominativiSearch($query, $search, $activeStabileId);
|
||||
|
|
@ -788,10 +824,10 @@ public function table(Table $table): Table
|
|||
$titolo = $this->resolveTitoloInquilinoForRow($record);
|
||||
return $this->formatLegacyDenominazione($titolo, $v);
|
||||
})
|
||||
->searchable(query: function (Builder $query, string $search) use ($activeStabileId): Builder {
|
||||
->searchable(query: function (Builder $query, string $search) use ($activeStabileId, $legacyTable): Builder {
|
||||
$model = $query->getModel();
|
||||
if ($model instanceof LegacyCondominNominativo) {
|
||||
return $query->where('inquil_nome', 'like', '%' . $search . '%');
|
||||
return $query->where($legacyTable . '.inquil_nome', 'like', '%' . $search . '%');
|
||||
}
|
||||
|
||||
return $this->applyDomainNominativiSearch($query, $search, $activeStabileId);
|
||||
|
|
@ -847,8 +883,7 @@ public function table(Table $table): Table
|
|||
|
||||
return RubricaUniversaleScheda::getUrl(['record' => $rubricaId], panel: 'admin-filament');
|
||||
}, shouldOpenInNewTab: true)
|
||||
->visible(fn($record): bool => (bool) $this->resolveRubricaIdForRow($record)),
|
||||
])
|
||||
->defaultSort('scala', 'asc');
|
||||
->visible(fn($record): bool => (bool) $this->resolveRubricaIdForRow($record)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
259
app/Filament/Pages/Fornitore/ImpostazioniArchivio.php
Normal file
259
app/Filament/Pages/Fornitore/ImpostazioniArchivio.php
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
<?php
|
||||
namespace App\Filament\Pages\Fornitore;
|
||||
|
||||
use App\Filament\Pages\Fornitore\Concerns\ResolvesOperatoreContext;
|
||||
use App\Filament\Pages\Gescon\FornitoreScheda;
|
||||
use App\Models\Fornitore;
|
||||
use App\Models\User;
|
||||
use App\Support\ArchivioPaths;
|
||||
use BackedEnum;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Page;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||
use Livewire\WithFileUploads;
|
||||
use UnitEnum;
|
||||
|
||||
class ImpostazioniArchivio extends Page
|
||||
{
|
||||
use ResolvesOperatoreContext;
|
||||
use WithFileUploads;
|
||||
|
||||
protected static ?string $navigationLabel = 'Impostazioni';
|
||||
|
||||
protected static ?string $title = 'Impostazioni fornitore';
|
||||
|
||||
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-cog-6-tooth';
|
||||
|
||||
protected static UnitEnum|string|null $navigationGroup = 'Fornitore';
|
||||
|
||||
protected static ?int $navigationSort = 5;
|
||||
|
||||
protected static ?string $slug = 'fornitore/impostazioni';
|
||||
|
||||
protected string $view = 'filament.pages.fornitore.impostazioni-archivio';
|
||||
|
||||
public ?Fornitore $fornitore = null;
|
||||
|
||||
public bool $missingAdminContext = false;
|
||||
|
||||
public string $tecnorepairMdbPath = '';
|
||||
|
||||
public string $lastImportOutput = '';
|
||||
|
||||
public $tecnorepairMdbUpload;
|
||||
|
||||
/** @var array<int, array<string, string>> */
|
||||
public array $archiveFolders = [];
|
||||
|
||||
/** @var array<int, array<string, string>> */
|
||||
public array $moduleRows = [];
|
||||
|
||||
/** @var array<string, mixed>|null */
|
||||
public ?array $googleWorkspaceStatus = null;
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
return $user instanceof User
|
||||
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'fornitore']);
|
||||
}
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
[$fornitore] = $this->resolveOperatoreContext(allowAdminWithoutSupplier: true);
|
||||
|
||||
if (! $fornitore instanceof Fornitore) {
|
||||
$this->missingAdminContext = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fornitore = $fornitore;
|
||||
$this->refreshArchiveSummary();
|
||||
}
|
||||
|
||||
public function saveUploadedTecnoRepairMdb(): void
|
||||
{
|
||||
if (! $this->fornitore instanceof Fornitore) {
|
||||
return;
|
||||
}
|
||||
|
||||
$upload = $this->tecnorepairMdbUpload;
|
||||
if (! $upload instanceof TemporaryUploadedFile) {
|
||||
Notification::make()->title('Seleziona prima un file MDB')->warning()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$extension = strtolower((string) $upload->getClientOriginalExtension());
|
||||
if ($extension !== 'mdb') {
|
||||
Notification::make()->title('Carica un file .mdb')->warning()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$relativeBase = $this->getArchiveRelativeBase();
|
||||
if ($relativeBase === null) {
|
||||
Notification::make()->title('Archivio fornitore non disponibile')->danger()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$filename = 'TecnoRepairDB-' . now()->format('Ymd-His') . '.mdb';
|
||||
$stored = $upload->storeAs($relativeBase . '/tecnorepair/imports', $filename, 'local');
|
||||
|
||||
$this->tecnorepairMdbPath = storage_path('app/' . $stored);
|
||||
$this->tecnorepairMdbUpload = null;
|
||||
$this->refreshArchiveSummary();
|
||||
|
||||
Notification::make()->title('Archivio TecnoRepair caricato')->body($filename)->success()->send();
|
||||
}
|
||||
|
||||
public function importTecnoRepairFromArchive(bool $dryRun = false): void
|
||||
{
|
||||
if (! $this->fornitore instanceof Fornitore) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mdbPath = trim($this->tecnorepairMdbPath);
|
||||
if ($mdbPath === '' || ! is_file($mdbPath)) {
|
||||
Notification::make()->title('Percorso MDB non valido')->warning()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$adminId = (int) ($this->fornitore->amministratore_id ?? 0);
|
||||
if ($adminId <= 0) {
|
||||
Notification::make()->title('Amministratore del fornitore non trovato')->danger()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Artisan::call('tecnorepair:import-legacy', [
|
||||
'amministratore' => $adminId,
|
||||
'--mdb' => $mdbPath,
|
||||
'--fornitore-id' => (int) $this->fornitore->id,
|
||||
'--force-primary' => true,
|
||||
'--dry-run' => $dryRun,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Notification::make()->title('Import TecnoRepair fallito')->body($e->getMessage())->danger()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->lastImportOutput = trim(Artisan::output());
|
||||
$this->refreshArchiveSummary();
|
||||
|
||||
Notification::make()
|
||||
->title($dryRun ? 'Simulazione TecnoRepair completata' : 'Import TecnoRepair completato')
|
||||
->body($this->lastImportOutput !== '' ? $this->lastImportOutput : 'Operazione completata.')
|
||||
->success()
|
||||
->send();
|
||||
}
|
||||
|
||||
public function getSchedaFornitoreUrl(): string
|
||||
{
|
||||
return FornitoreScheda::getUrl(['record' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
|
||||
}
|
||||
|
||||
public function getTicketsUrl(): string
|
||||
{
|
||||
return TicketOperativi::getUrl(['fornitore' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
|
||||
}
|
||||
|
||||
public function getProdottiUrl(): string
|
||||
{
|
||||
return ProdottiCatalogo::getUrl(['fornitore' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
|
||||
}
|
||||
|
||||
public function getGoogleConnectUrl(): string
|
||||
{
|
||||
return route('oauth.google.redirect');
|
||||
}
|
||||
|
||||
public function getGoogleDisconnectUrl(): string
|
||||
{
|
||||
return route('oauth.google.disconnect');
|
||||
}
|
||||
|
||||
private function refreshArchiveSummary(): void
|
||||
{
|
||||
$relativeBase = $this->getArchiveRelativeBase();
|
||||
$absoluteBase = $relativeBase ? storage_path('app/' . $relativeBase) : null;
|
||||
|
||||
if ($relativeBase !== null) {
|
||||
foreach ([
|
||||
'documenti',
|
||||
'rubrica',
|
||||
'fe',
|
||||
'prodotti',
|
||||
'comunicazioni',
|
||||
'tecnorepair/imports',
|
||||
'tecnorepair/allegati',
|
||||
'temp/upload',
|
||||
'temp/processing',
|
||||
'logs',
|
||||
] as $folder) {
|
||||
Storage::disk('local')->makeDirectory($relativeBase . '/' . $folder);
|
||||
}
|
||||
}
|
||||
|
||||
$this->archiveFolders = $relativeBase === null ? [] : [
|
||||
['label' => 'Base archivio', 'path' => (string) $absoluteBase],
|
||||
['label' => 'Rubrica fornitore', 'path' => storage_path('app/' . $relativeBase . '/rubrica')],
|
||||
['label' => 'FE fornitore', 'path' => storage_path('app/' . $relativeBase . '/fe')],
|
||||
['label' => 'Prodotti e catalogo', 'path' => storage_path('app/' . $relativeBase . '/prodotti')],
|
||||
['label' => 'Comunicazioni / Post-it', 'path' => storage_path('app/' . $relativeBase . '/comunicazioni')],
|
||||
['label' => 'TecnoRepair import', 'path' => storage_path('app/' . $relativeBase . '/tecnorepair/imports')],
|
||||
];
|
||||
|
||||
if ($relativeBase !== null && $this->tecnorepairMdbPath === '') {
|
||||
$latest = collect(Storage::disk('local')->files($relativeBase . '/tecnorepair/imports'))
|
||||
->filter(fn(string $path): bool => str_ends_with(strtolower($path), '.mdb'))
|
||||
->sortDesc()
|
||||
->first();
|
||||
|
||||
if (is_string($latest) && $latest !== '') {
|
||||
$this->tecnorepairMdbPath = storage_path('app/' . $latest);
|
||||
}
|
||||
}
|
||||
|
||||
$stats = $this->fornitore?->tecnorepair_stats ?? ['total' => 0, 'open' => 0, 'closed' => 0, 'serials' => 0];
|
||||
$this->googleWorkspaceStatus = $this->resolveGoogleWorkspaceStatus();
|
||||
$this->moduleRows = [
|
||||
['module' => 'Rubrica fornitore', 'status' => 'pronto', 'note' => 'Vista fornitore filtrata ma agganciata all\'anagrafica unica.'],
|
||||
['module' => 'Google Workspace', 'status' => data_get($this->googleWorkspaceStatus, 'connected', false) ? 'collegato' : 'da collegare', 'note' => 'Rubrica e sincronizzazioni smartphone riusano l\'account Google del contesto amministratore.'],
|
||||
['module' => 'TecnoRepair MDB', 'status' => ((int) ($stats['total'] ?? 0) > 0) ? 'importato' : 'da importare', 'note' => 'Schede: ' . (int) ($stats['total'] ?? 0) . ' · aperte: ' . (int) ($stats['open'] ?? 0) . ' · chiuse: ' . (int) ($stats['closed'] ?? 0)],
|
||||
['module' => 'Catalogo fornitore', 'status' => 'attivo', 'note' => 'Il catalogo vero resta nella pagina Prodotti.'],
|
||||
['module' => 'Comunicazioni / Post-it', 'status' => 'predisposto', 'note' => 'Cartelle e contesto archivio pronti per agganciare chiamate, post-it ed email.'],
|
||||
['module' => 'FE e documenti', 'status' => 'predisposto', 'note' => 'Archivio separato per FE, documenti e flussi contabili del fornitore.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function resolveGoogleWorkspaceStatus(): ?array
|
||||
{
|
||||
$amministratore = $this->fornitore?->amministratore;
|
||||
if (! $amministratore) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$oauth = (array) (($amministratore->impostazioni['google']['oauth'] ?? null) ?: []);
|
||||
|
||||
return [
|
||||
'connected' => (bool) ($oauth['connected'] ?? false),
|
||||
'email' => (string) ($oauth['email'] ?? ''),
|
||||
'name' => (string) ($oauth['name'] ?? ''),
|
||||
'connected_at' => (string) ($oauth['connected_at'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
private function getArchiveRelativeBase(): ?string
|
||||
{
|
||||
if (! $this->fornitore instanceof Fornitore) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ArchivioPaths::fornitoreBase($this->fornitore, $this->fornitore->amministratore);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<x-filament-panels::page>
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-lg font-semibold">Impostazioni fornitore e archivio operativo</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
@if($this->fornitore)
|
||||
Qui concentriamo archivio fornitore, moduli attivabili, import TecnoRepair e collegamento Google di {{ $this->fornitore->ragione_sociale ?? ('Fornitore #' . $this->fornitore->id) }}.
|
||||
@else
|
||||
Seleziona un fornitore per aprire questa vista.
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<a href="{{ $this->getSchedaFornitoreUrl() }}" class="inline-flex items-center rounded-md bg-gray-800 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-700">Scheda fornitore</a>
|
||||
<a href="{{ $this->getTicketsUrl() }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50">Ticket</a>
|
||||
<a href="{{ $this->getProdottiUrl() }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50">Catalogo fornitore</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($this->missingAdminContext)
|
||||
<div class="rounded-xl border border-amber-300 bg-amber-50 p-4 text-sm text-amber-800">
|
||||
Questa vista richiede un fornitore selezionato.
|
||||
</div>
|
||||
@else
|
||||
<div class="grid gap-4 xl:grid-cols-[1.4fr,1fr]">
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
<div class="text-sm font-semibold">Archivio fornitore</div>
|
||||
<div class="mt-1 text-xs text-gray-500">Il fornitore ora ha una struttura archivio dedicata, parallela a quella degli stabili, pronta per rubrica, FE, prodotti, comunicazioni e import tecnici.</div>
|
||||
|
||||
<div class="mt-4 space-y-2 text-sm">
|
||||
@foreach($archiveFolders as $row)
|
||||
<div class="rounded-lg border bg-slate-50 p-3">
|
||||
<div class="font-medium text-slate-900">{{ $row['label'] }}</div>
|
||||
<div class="mt-1 break-all font-mono text-[11px] text-slate-600">{{ $row['path'] }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
<div class="text-sm font-semibold">TecnoRepair MDB</div>
|
||||
<div class="mt-1 text-xs text-gray-500">Puoi caricare un archivio MDB dalla pagina web oppure indicare un percorso già disponibile sul server, poi lanciare la sincronizzazione verso il fornitore.</div>
|
||||
|
||||
<div class="mt-4 grid gap-3 md:grid-cols-2">
|
||||
<label class="block text-sm md:col-span-2">
|
||||
<span class="mb-1 block font-medium">Percorso MDB attivo</span>
|
||||
<input type="text" wire:model.defer="tecnorepairMdbPath" class="w-full rounded-lg border-gray-300" placeholder="/percorso/TecnoRepairDB.mdb" />
|
||||
</label>
|
||||
<label class="block text-sm md:col-span-2">
|
||||
<span class="mb-1 block font-medium">Carica archivio MDB</span>
|
||||
<input type="file" wire:model="tecnorepairMdbUpload" accept=".mdb,application/octet-stream" class="w-full rounded-lg border-gray-300 text-sm" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<x-filament::button type="button" color="gray" wire:click="saveUploadedTecnoRepairMdb">Salva MDB in archivio fornitore</x-filament::button>
|
||||
<x-filament::button type="button" color="primary" wire:click="importTecnoRepairFromArchive(false)">Importa TecnoRepair</x-filament::button>
|
||||
<x-filament::button type="button" color="info" wire:click="importTecnoRepairFromArchive(true)">Simula import</x-filament::button>
|
||||
</div>
|
||||
|
||||
@if(filled($lastImportOutput))
|
||||
<div class="mt-4 whitespace-pre-wrap rounded-lg border border-emerald-200 bg-emerald-50 p-3 text-xs text-emerald-900">{{ $lastImportOutput }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
<div class="text-sm font-semibold">Moduli fornitore</div>
|
||||
<div class="mt-3 space-y-2">
|
||||
@foreach($moduleRows as $row)
|
||||
<div class="rounded-lg border p-3 text-sm">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="font-medium">{{ $row['module'] }}</div>
|
||||
<span class="rounded-full bg-slate-100 px-2 py-1 text-[11px] font-semibold text-slate-700">{{ $row['status'] }}</span>
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-slate-500">{{ $row['note'] }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
<div class="text-sm font-semibold">Google Workspace</div>
|
||||
@if($googleWorkspaceStatus)
|
||||
<div class="mt-3 space-y-2 text-sm">
|
||||
<div><span class="font-medium">Stato:</span> {{ $googleWorkspaceStatus['connected'] ? 'Collegato' : 'Non collegato' }}</div>
|
||||
<div><span class="font-medium">Account:</span> {{ $googleWorkspaceStatus['email'] !== '' ? $googleWorkspaceStatus['email'] : '-' }}</div>
|
||||
<div><span class="font-medium">Nome:</span> {{ $googleWorkspaceStatus['name'] !== '' ? $googleWorkspaceStatus['name'] : '-' }}</div>
|
||||
<div><span class="font-medium">Ultimo collegamento:</span> {{ $googleWorkspaceStatus['connected_at'] !== '' ? $googleWorkspaceStatus['connected_at'] : '-' }}</div>
|
||||
</div>
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
<a href="{{ $this->getGoogleConnectUrl() }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50">Collega / aggiorna Google</a>
|
||||
@if($googleWorkspaceStatus['connected'])
|
||||
<form method="POST" action="{{ $this->getGoogleDisconnectUrl() }}">
|
||||
@csrf
|
||||
<button type="submit" class="inline-flex items-center rounded-md bg-rose-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-rose-500">Scollega</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 text-xs text-gray-500">Questo collegamento prepara la sincronizzazione rubrica lato fornitore e l'uso dei dati anche sul cellulare tramite l'account Google già governato dal backend.</div>
|
||||
@else
|
||||
<div class="mt-3 text-sm text-gray-500">Contesto amministratore Google non disponibile per questo fornitore.</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-filament-panels::page>
|
||||
Loading…
Reference in New Issue
Block a user