Batch 3: Integrări placeholder + Backup tenant

═══ Integrări (Marketing → Integrări) ═══
- /app/integrations Page cu 6 carduri (Telegram/WhatsApp/Google Ads/FB/SMS/Webhook)
- Toggle on/off per integrare; salvare în settings.integrations JSON
- Câmpuri specifice per integrare (token/key/id/secret)
- Banner explicativ: 'placeholder UI — implementare separată'

═══ Backup tenant ═══
- TenantBackupService::export($company) → ZIP cu:
  • data/ (1 JSON per tabel: clients/vehicles/leads/deals/work_orders cu sub-relații/...)
  • media/ (logo + favicon)
  • manifest.json (metadata + counts)
- /app/backup Page cu buton 'Descarcă backup acum'
- Streaming download cu deleteFileAfterSend
- Util pentru: backup local, migrare, audit, GDPR right-to-erasure

Total tenant routes: 104.
Toate cele ~26 module din prototip implementate (sau echivalent funcțional).
This commit is contained in:
2026-05-07 17:36:00 +00:00
parent 4b3201ca1c
commit 6c72fc7db1
5 changed files with 380 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Filament\Tenant\Pages;
use App\Models\Central\Company;
use App\Services\TenantBackupService;
use App\Tenancy\TenantManager;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
class Backup extends Page
{
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-archive-box-arrow-down';
protected static ?string $navigationLabel = 'Backup';
protected static string|\UnitEnum|null $navigationGroup = 'Admin';
protected static ?int $navigationSort = 96;
protected static ?string $title = 'Backup & Export date';
protected string $view = 'filament.tenant.pages.backup';
public function downloadBackup()
{
$tenant = app(TenantManager::class)->current();
if (! $tenant) abort(404);
// Re-fetch via central scope to avoid issues.
$company = Company::withoutGlobalScopes()->find($tenant->id);
if (! $company) abort(404);
$svc = app(TenantBackupService::class);
$file = $svc->export($company);
$filename = $svc->filename($company);
return response()->download($file, $filename, [
'Content-Type' => 'application/zip',
])->deleteFileAfterSend();
}
}