feat: import legacy assemblee and fix label preview
This commit is contained in:
parent
df441bcc43
commit
d8d5a3e671
|
|
@ -24,7 +24,7 @@ class ImportGesconFullPipeline extends Command
|
|||
{--dry-run : Simula senza scrivere sulle tabelle dominio}
|
||||
{--limit= : Limita numero record per debug}
|
||||
{--reset-temp : Svuota staging prima di importare}
|
||||
{--solo= : Step singolo: unita|relazioni|soggetti|diritti|millesimi|voci|operazioni|rate|incassi|giroconti|straord|addebiti|detrazioni|tutto}
|
||||
{--solo= : Step singolo: assemblee|unita|relazioni|soggetti|diritti|millesimi|voci|operazioni|rate|incassi|giroconti|straord|addebiti|detrazioni|tutto}
|
||||
{--no-views : Non ricrea le viste QA}
|
||||
{--force-mapping : Applica mapping anche sovrascrivendo valori esistenti}
|
||||
{--fill-missing-millesimi : Crea righe mancanti a zero per ogni unita/tabella (uso eccezionale)}
|
||||
|
|
@ -35,6 +35,7 @@ class ImportGesconFullPipeline extends Command
|
|||
|
||||
private array $stepsOrder = [
|
||||
'stabili',
|
||||
'assemblee',
|
||||
'unita',
|
||||
'relazioni',
|
||||
'soggetti',
|
||||
|
|
@ -3915,6 +3916,95 @@ private function stepDetrazioni(?int $limit): int
|
|||
return $count;
|
||||
}
|
||||
|
||||
private function stepAssemblee(?int $limit): int
|
||||
{
|
||||
if (! Schema::hasTable('assemblee')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$stabileId = $this->stabileId ?: $this->resolveStabileId();
|
||||
$stabile = trim((string) ($this->option('stabile') ?? ''));
|
||||
if (! $stabileId || $stabile === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$sources = $this->resolveAssembleeMdbSources($stabile);
|
||||
if ($sources === []) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$assembleeColumns = Schema::getColumnListing('assemblee');
|
||||
$canMatch = in_array('stabile_id', $assembleeColumns, true)
|
||||
&& in_array('tipo', $assembleeColumns, true)
|
||||
&& in_array('data_prima_convocazione', $assembleeColumns, true)
|
||||
&& in_array('data_seconda_convocazione', $assembleeColumns, true);
|
||||
|
||||
$processed = 0;
|
||||
foreach ($sources as $source) {
|
||||
$rows = $this->mdbExportToRows($source['path'], ['Singolo_anno_assemblee', 'singolo_anno_assemblee', 'assemblee']);
|
||||
if ($rows === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($rows as $row) {
|
||||
if ($limit !== null && $processed >= $limit) {
|
||||
return $processed;
|
||||
}
|
||||
|
||||
$firstDate = $this->normalizeLegacyDateTime($row['dt_1_convoc'] ?? null, $row['ora_1_convoc'] ?? null);
|
||||
$secondDate = $this->normalizeLegacyDateTime($row['dt_2_convoc'] ?? null, $row['ora_2_convoc'] ?? null);
|
||||
if ($firstDate === null && $secondDate === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tipo = $this->normalizeLegacyAssembleaType($row['ordin_straord'] ?? null);
|
||||
$luogo = $this->firstNonEmptyStr([
|
||||
$row['luogo_2_convoc'] ?? null,
|
||||
$row['luogo_1_convoc'] ?? null,
|
||||
], 255);
|
||||
$reference = $secondDate ?? $firstDate;
|
||||
$referenceTs = $reference ? strtotime($reference) : false;
|
||||
$note = $this->buildLegacyAssembleaNote($row, (string) ($source['legacy_year'] ?? ''));
|
||||
|
||||
$payload = [
|
||||
'stabile_id' => $stabileId,
|
||||
'tipo' => $tipo,
|
||||
'data_assemblea' => $reference,
|
||||
'data_prima_convocazione' => $firstDate,
|
||||
'data_seconda_convocazione' => $secondDate,
|
||||
'luogo' => $luogo,
|
||||
'note' => $note,
|
||||
'stato' => ($referenceTs !== false && $referenceTs < time()) ? 'svolta' : 'convocata',
|
||||
'data_convocazione' => $firstDate ? substr($firstDate, 0, 10) : null,
|
||||
'data_svolgimento' => ($referenceTs !== false && $referenceTs < time()) ? substr($reference, 0, 10) : null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
|
||||
if ($canMatch) {
|
||||
$match = [
|
||||
'stabile_id' => $stabileId,
|
||||
'tipo' => $tipo,
|
||||
'data_prima_convocazione' => $firstDate,
|
||||
'data_seconda_convocazione' => $secondDate,
|
||||
];
|
||||
|
||||
if (! $this->isDryRun) {
|
||||
DB::table('assemblee')->updateOrInsert($match, array_merge($payload, [
|
||||
'updated_at' => now(),
|
||||
]));
|
||||
}
|
||||
} else {
|
||||
$this->dynamicInsert('assemblee', $payload);
|
||||
}
|
||||
|
||||
$processed++;
|
||||
}
|
||||
}
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
private function stub(string $table, ?int $limit): int
|
||||
{
|
||||
// Placeholder: sostituire con logica di lettura da MDB / staging
|
||||
|
|
@ -5252,6 +5342,175 @@ private function normalizeLegacyDate(?string $value): ?string
|
|||
return date('Y-m-d', $ts);
|
||||
}
|
||||
|
||||
private function normalizeLegacyDateTime(?string $dateValue, ?string $timeValue = null): ?string
|
||||
{
|
||||
if (! is_string($dateValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dateValue = trim($dateValue);
|
||||
if ($dateValue === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dateToken = preg_split('/\s+/', $dateValue)[0] ?? '';
|
||||
$dateToken = trim((string) $dateToken);
|
||||
if ($dateToken === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$datePart = null;
|
||||
foreach (['!m/d/y', '!d/m/y', '!m/d/Y', '!d/m/Y', '!Y-m-d'] as $format) {
|
||||
$parsed = \DateTime::createFromFormat($format, $dateToken);
|
||||
if ($parsed instanceof \DateTime) {
|
||||
$datePart = $parsed->format('Y-m-d');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($datePart === null) {
|
||||
$ts = strtotime($dateValue);
|
||||
if ($ts === false) {
|
||||
return null;
|
||||
}
|
||||
$datePart = date('Y-m-d', $ts);
|
||||
}
|
||||
|
||||
return $datePart . ' ' . ($this->normalizeLegacyTime($timeValue) ?? '00:00:00');
|
||||
}
|
||||
|
||||
private function normalizeLegacyTime(?string $value): ?string
|
||||
{
|
||||
if (! is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = str_replace([',', '.'], ':', $value);
|
||||
$value = preg_replace('/\s+/', '', $value ?? '');
|
||||
if ($value === null || $value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('/^(\d{1,2})$/', $value, $matches)) {
|
||||
return sprintf('%02d:00:00', (int) $matches[1]);
|
||||
}
|
||||
|
||||
if (preg_match('/^(\d{1,2}):(\d{1,2})$/', $value, $matches)) {
|
||||
return sprintf('%02d:%02d:00', (int) $matches[1], (int) $matches[2]);
|
||||
}
|
||||
|
||||
if (preg_match('/^(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $value, $matches)) {
|
||||
return sprintf('%02d:%02d:%02d', (int) $matches[1], (int) $matches[2], (int) $matches[3]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function normalizeLegacyAssembleaType(?string $value): string
|
||||
{
|
||||
$normalized = Str::lower(trim((string) $value));
|
||||
|
||||
return str_contains($normalized, 'stra') ? 'straordinaria' : 'ordinaria';
|
||||
}
|
||||
|
||||
private function buildLegacyAssembleaNote(array $row, string $legacyYear): ?string
|
||||
{
|
||||
$parts = [];
|
||||
|
||||
$numero = trim((string) ($row['num_ass'] ?? ''));
|
||||
if ($numero !== '') {
|
||||
$parts[] = 'Assemblea legacy n. ' . $numero;
|
||||
}
|
||||
|
||||
if ($legacyYear !== '') {
|
||||
$parts[] = 'Cartella legacy: ' . $legacyYear;
|
||||
}
|
||||
|
||||
$noteConvocazione = trim((string) ($row['note_convocaz'] ?? ''));
|
||||
if ($noteConvocazione !== '') {
|
||||
$parts[] = 'Note convocazione: ' . $noteConvocazione;
|
||||
}
|
||||
|
||||
$noteAssemblea = trim((string) ($row['note_assemblea'] ?? ''));
|
||||
if ($noteAssemblea !== '') {
|
||||
$parts[] = 'Note assemblea: ' . $noteAssemblea;
|
||||
}
|
||||
|
||||
$noteInterne = trim((string) ($row['note_assemblea_int'] ?? ''));
|
||||
if ($noteInterne !== '') {
|
||||
$parts[] = 'Note interne legacy: ' . $noteInterne;
|
||||
}
|
||||
|
||||
$ordineGiorno = trim((string) ($row['ordine_del_giorno'] ?? ''));
|
||||
if ($ordineGiorno !== '') {
|
||||
$parts[] = 'Ordine del giorno legacy:' . PHP_EOL . $ordineGiorno;
|
||||
}
|
||||
|
||||
if ($parts === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return implode(PHP_EOL . PHP_EOL, $parts);
|
||||
}
|
||||
|
||||
private function resolveAssembleeMdbSources(string $stabile): array
|
||||
{
|
||||
$root = rtrim((string) ($this->option('path') ?: '/mnt/gescon-archives/gescon'), '/');
|
||||
$stableDir = $root . '/' . $stabile;
|
||||
if (! is_dir($stableDir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$anno = trim((string) ($this->option('anno') ?? ''));
|
||||
$sources = [];
|
||||
if ($anno !== '' && strcasecmp($anno, 'all') !== 0) {
|
||||
$candidates = array_unique(array_filter([
|
||||
$stableDir . '/' . $anno . '/singolo_anno.mdb',
|
||||
is_numeric($anno) ? $stableDir . '/' . sprintf('%04d', (int) $anno) . '/singolo_anno.mdb' : null,
|
||||
]));
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
if (is_string($candidate) && is_file($candidate)) {
|
||||
$sources[] = [
|
||||
'path' => $candidate,
|
||||
'legacy_year' => basename(dirname($candidate)),
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ((array) glob($stableDir . '/*/singolo_anno.mdb') as $candidate) {
|
||||
if (! is_string($candidate) || ! is_file($candidate)) {
|
||||
continue;
|
||||
}
|
||||
$sources[] = [
|
||||
'path' => $candidate,
|
||||
'legacy_year' => basename(dirname($candidate)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($sources === []) {
|
||||
$resolved = $this->resolveCondominMdbForStabile($stabile, is_numeric($anno) ? sprintf('%04d', (int) $anno) : null);
|
||||
if ($resolved !== null && ! empty($resolved['path']) && is_file((string) $resolved['path'])) {
|
||||
$sources[] = [
|
||||
'path' => (string) $resolved['path'],
|
||||
'legacy_year' => (string) ($resolved['legacy_year'] ?? basename(dirname((string) $resolved['path']))),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($sources, static function (array $left, array $right): int {
|
||||
return strcmp((string) ($left['legacy_year'] ?? ''), (string) ($right['legacy_year'] ?? ''));
|
||||
});
|
||||
|
||||
return array_values(array_unique($sources, SORT_REGULAR));
|
||||
}
|
||||
|
||||
private function resolveLegacySnapshotYear(?string $legacyYear, ?object $row = null): ?int
|
||||
{
|
||||
$resolved = $this->resolveAnnoFromLegacyYear($legacyYear);
|
||||
|
|
|
|||
|
|
@ -3,16 +3,17 @@
|
|||
|
||||
use App\Filament\Pages\Strumenti\DocumentiArchivio;
|
||||
use App\Models\Assemblea;
|
||||
use App\Models\AssembleaVerbale;
|
||||
use App\Models\Stabile;
|
||||
use App\Models\User;
|
||||
use App\Support\StabileContext;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Pages\Page;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\QueryException;
|
||||
use UnitEnum;
|
||||
|
||||
class AssembleeHub extends Page
|
||||
|
|
@ -75,6 +76,7 @@ public function getStatsProperty(): array
|
|||
|
||||
try {
|
||||
$query = Assemblea::query()->where('stabile_id', $stabileId);
|
||||
$hasVerbali = class_exists(AssembleaVerbale::class) && Schema::hasTable('assemblee_verbali');
|
||||
|
||||
return [
|
||||
'totale' => (clone $query)->count(),
|
||||
|
|
@ -87,7 +89,7 @@ public function getStatsProperty(): array
|
|||
->orWhereDate('data_seconda_convocazione', '>=', $today->toDateString());
|
||||
})
|
||||
->count(),
|
||||
'con_verbale' => (clone $query)->whereHas('verbale')->count(),
|
||||
'con_verbale' => $hasVerbali ? (clone $query)->whereHas('verbale')->count() : 0,
|
||||
];
|
||||
} catch (QueryException) {
|
||||
return ['totale' => 0, 'convocate' => 0, 'in_calendario' => 0, 'con_verbale' => 0];
|
||||
|
|
@ -102,15 +104,41 @@ public function getAssembleeRowsProperty(): Collection
|
|||
}
|
||||
|
||||
try {
|
||||
return Assemblea::query()
|
||||
->with(['verbale:id,assemblea_id'])
|
||||
->withCount(['ordineGiorno', 'convocazioni', 'presenze', 'documenti'])
|
||||
$query = Assemblea::query()
|
||||
->where('stabile_id', $stabileId)
|
||||
->orderByDesc('data_seconda_convocazione')
|
||||
->orderByDesc('data_prima_convocazione')
|
||||
->orderByDesc('id')
|
||||
->limit(16)
|
||||
->get();
|
||||
->limit(16);
|
||||
|
||||
if (Schema::hasTable('assemblee_verbali')) {
|
||||
$query->with(['verbale:id,assemblea_id']);
|
||||
}
|
||||
|
||||
$withCount = [];
|
||||
if (Schema::hasTable('ordine_giorno')) {
|
||||
$withCount[] = 'ordineGiorno';
|
||||
}
|
||||
if (Schema::hasTable('convocazioni')) {
|
||||
$withCount[] = 'convocazioni';
|
||||
}
|
||||
|
||||
if ($withCount !== []) {
|
||||
$query->withCount($withCount);
|
||||
}
|
||||
|
||||
return $query->get()->map(function (Assemblea $assemblea): Assemblea {
|
||||
$assemblea->ordine_giorno_count = (int) ($assemblea->ordine_giorno_count ?? 0);
|
||||
$assemblea->convocazioni_count = (int) ($assemblea->convocazioni_count ?? 0);
|
||||
$assemblea->presenze_count = 0;
|
||||
$assemblea->documenti_count = 0;
|
||||
|
||||
if (! $assemblea->relationLoaded('verbale')) {
|
||||
$assemblea->setRelation('verbale', null);
|
||||
}
|
||||
|
||||
return $assemblea;
|
||||
});
|
||||
} catch (QueryException) {
|
||||
return collect();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ public function mount(): void
|
|||
'with_voci' => true,
|
||||
'with_banche' => true,
|
||||
'with_gestioni' => false,
|
||||
'with_assemblee' => false,
|
||||
'with_operazioni' => false,
|
||||
'with_rate' => false,
|
||||
'with_incassi' => false,
|
||||
|
|
@ -417,6 +418,7 @@ public function form(Schema $schema): Schema
|
|||
}),
|
||||
Checkbox::make('with_banche')->label('Banche / casse'),
|
||||
Checkbox::make('with_gestioni')->label('Gestioni (anni)'),
|
||||
Checkbox::make('with_assemblee')->label('Assemblee legacy'),
|
||||
Checkbox::make('with_operazioni')
|
||||
->label('Operazioni')
|
||||
->reactive()
|
||||
|
|
@ -968,6 +970,7 @@ public function eseguiImportSelezionato(EssentialImportService $service): void
|
|||
'with_voci' => (bool) ($state['with_voci'] ?? false),
|
||||
'with_banche' => (bool) ($state['with_banche'] ?? false),
|
||||
'with_gestioni' => (bool) ($state['with_gestioni'] ?? false),
|
||||
'with_assemblee' => (bool) ($state['with_assemblee'] ?? false),
|
||||
'with_operazioni' => (bool) ($state['with_operazioni'] ?? false),
|
||||
'with_rate' => (bool) ($state['with_rate'] ?? false),
|
||||
'with_incassi' => (bool) ($state['with_incassi'] ?? false),
|
||||
|
|
@ -1008,6 +1011,7 @@ public function eseguiImportSelezionato(EssentialImportService $service): void
|
|||
'millesimi',
|
||||
'voci',
|
||||
'banche',
|
||||
'assemblee',
|
||||
'operazioni',
|
||||
'rate',
|
||||
'incassi',
|
||||
|
|
|
|||
|
|
@ -959,6 +959,7 @@ public function getGenericLabelPreviewProperty(): array
|
|||
'nfc_payload' => (string) ($qrProfiles['xml_nfc'] ?? ''),
|
||||
'qr_payload_length' => (int) ($qrProfiles['xml_open_length'] ?? 0),
|
||||
'nfc_payload_length' => (int) ($qrProfiles['xml_nfc_length'] ?? 0),
|
||||
'qr_markup' => $this->buildGenericLabelQrMarkup((string) ($qrProfiles['xml_open'] ?? '')),
|
||||
'amazon_url' => $amazonUrl,
|
||||
];
|
||||
|
||||
|
|
@ -991,6 +992,42 @@ public function getGenericLabelPreviewProperty(): array
|
|||
];
|
||||
}
|
||||
|
||||
private function buildGenericLabelQrMarkup(string $data): string
|
||||
{
|
||||
$data = trim($data);
|
||||
if ($data === '') {
|
||||
return '<span aria-hidden="true"></span>';
|
||||
}
|
||||
|
||||
if (class_exists(\chillerlan\QRCode\QROptions::class) && class_exists(\chillerlan\QRCode\QRCode::class)) {
|
||||
$options = new \chillerlan\QRCode\QROptions([
|
||||
'outputType' => \chillerlan\QRCode\QRCode::OUTPUT_MARKUP_SVG,
|
||||
'eccLevel' => \chillerlan\QRCode\QRCode::ECC_M,
|
||||
'addQuietzone' => true,
|
||||
'quietzoneSize' => 1,
|
||||
'connectPaths' => true,
|
||||
]);
|
||||
|
||||
$svg = (new \chillerlan\QRCode\QRCode($options))->render($data);
|
||||
|
||||
if (str_starts_with($svg, 'data:image/svg+xml;base64,')) {
|
||||
$decoded = base64_decode(substr($svg, strlen('data:image/svg+xml;base64,')), true);
|
||||
|
||||
if (is_string($decoded) && $decoded !== '') {
|
||||
$svg = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
if (str_contains($svg, '<svg')) {
|
||||
$svg = preg_replace('/<svg\b/', '<svg aria-label="QR anteprima etichetta" role="img" preserveAspectRatio="xMidYMid meet"', $svg, 1) ?: $svg;
|
||||
|
||||
return $svg;
|
||||
}
|
||||
}
|
||||
|
||||
return '<img alt="QR anteprima etichetta" src="https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=' . rawurlencode($data) . '">';
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function getAudienceGroupsProperty(): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -14,6 +13,7 @@ class Assemblea extends Model
|
|||
protected $fillable = [
|
||||
'stabile_id',
|
||||
'tipo',
|
||||
'data_assemblea',
|
||||
'data_prima_convocazione',
|
||||
'data_seconda_convocazione',
|
||||
'luogo',
|
||||
|
|
@ -25,6 +25,7 @@ class Assemblea extends Model
|
|||
];
|
||||
|
||||
protected $casts = [
|
||||
'data_assemblea' => 'datetime',
|
||||
'data_prima_convocazione' => 'datetime',
|
||||
'data_seconda_convocazione' => 'datetime',
|
||||
'data_convocazione' => 'date',
|
||||
|
|
@ -70,7 +71,7 @@ public function presenze()
|
|||
*/
|
||||
public function verbale()
|
||||
{
|
||||
return $this->hasOne(Verbale::class, 'assemblea_id');
|
||||
return $this->hasOne(AssembleaVerbale::class, 'assemblea_id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -171,4 +171,5 @@ protected function resolveSupplierCatalogUrl(): string
|
|||
|
||||
return TicketOperativi::getUrl(panel: 'admin-filament');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (Schema::hasTable('assemblee')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schema::create('assemblee', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->foreignId('stabile_id')->nullable()->constrained('stabili')->nullOnDelete();
|
||||
$table->string('tipo', 50)->default('ordinaria');
|
||||
$table->dateTime('data_assemblea')->nullable()->index();
|
||||
$table->dateTime('data_prima_convocazione')->nullable()->index();
|
||||
$table->dateTime('data_seconda_convocazione')->nullable()->index();
|
||||
$table->date('data_convocazione')->nullable();
|
||||
$table->date('data_svolgimento')->nullable();
|
||||
$table->string('luogo')->nullable();
|
||||
$table->text('note')->nullable();
|
||||
$table->string('stato', 50)->default('bozza')->index();
|
||||
$table->foreignId('creato_da_user_id')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['stabile_id', 'tipo']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('assemblee');
|
||||
}
|
||||
};
|
||||
|
|
@ -120,6 +120,35 @@ @media (min-width: 64rem) {
|
|||
|
||||
@media (max-width: 63.998rem),
|
||||
(hover: none) and (pointer: coarse) {
|
||||
.fi-header {
|
||||
flex-direction: column !important;
|
||||
align-items: stretch !important;
|
||||
gap: calc(var(--spacing) * 3) !important;
|
||||
}
|
||||
|
||||
.fi-header>div:first-child {
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
.fi-header-actions-ctn,
|
||||
.fi-ac.fi-align-start {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
flex-wrap: wrap !important;
|
||||
align-items: stretch !important;
|
||||
justify-content: flex-start !important;
|
||||
row-gap: calc(var(--spacing) * 2) !important;
|
||||
}
|
||||
|
||||
.fi-header-actions-ctn .fi-btn,
|
||||
.fi-ac.fi-align-start .fi-btn,
|
||||
.fi-header-actions-ctn .fi-dropdown,
|
||||
.fi-ac.fi-align-start .fi-dropdown {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.fi-body.fi-body-has-navigation .fi-topbar {
|
||||
position: static !important;
|
||||
top: auto !important;
|
||||
|
|
|
|||
|
|
@ -335,7 +335,9 @@
|
|||
</div>
|
||||
|
||||
<div class="flex flex-col items-center justify-end gap-3">
|
||||
<div class="{{ $qrClass }} rounded-xl border border-slate-300 bg-[linear-gradient(135deg,#0f172a_16%,transparent_16%,transparent_34%,#0f172a_34%,#0f172a_50%,transparent_50%,transparent_66%,#0f172a_66%,#0f172a_84%,transparent_84%)] bg-[length:16px_16px] bg-white"></div>
|
||||
<div class="{{ $qrClass }} flex items-center justify-center overflow-hidden rounded-xl border border-slate-300 bg-white p-1 text-slate-900 [&_img]:h-full [&_img]:w-full [&_img]:object-contain [&_svg]:h-full [&_svg]:w-full">
|
||||
{!! data_get($preview, 'payload.qr_markup', '') !!}
|
||||
</div>
|
||||
<div class="text-center text-[10px] font-semibold uppercase tracking-[0.2em] text-slate-500">QR</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -374,7 +376,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="{{ $isBottomQr ? 'flex justify-center pt-1' : ($qrPosition === 'right-top' ? 'flex items-start justify-end' : 'flex items-center justify-end') }} shrink-0">
|
||||
<div class="{{ $qrClass }} rounded-xl border border-slate-300 bg-[linear-gradient(135deg,#0f172a_16%,transparent_16%,transparent_34%,#0f172a_34%,#0f172a_50%,transparent_50%,transparent_66%,#0f172a_66%,#0f172a_84%,transparent_84%)] bg-[length:16px_16px] bg-white"></div>
|
||||
<div class="{{ $qrClass }} flex items-center justify-center overflow-hidden rounded-xl border border-slate-300 bg-white p-1 text-slate-900 [&_img]:h-full [&_img]:w-full [&_img]:object-contain [&_svg]:h-full [&_svg]:w-full">
|
||||
{!! data_get($preview, 'payload.qr_markup', '') !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ RSYNC_ARGS=(
|
|||
--exclude=node_modules/
|
||||
--exclude=vendor/
|
||||
--exclude=bootstrap/cache/
|
||||
--exclude=public/build/
|
||||
)
|
||||
|
||||
if [[ "$DRY_RUN" == "yes" ]]; then
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user