Skip to content

Commit 19c93a0

Browse files
committed
feat(import-wizard): add new companies counter to preview stats
Track unique new company names during import preview processing. Shows count of companies that will be created when importing People/Opportunities with company references. - Add newCompanies property to ImportSessionData - Accumulate unique new company names across chunks - Display new companies count in preview stats area - Remove per-row match badges (simplify UI)
1 parent 54bb02d commit 19c93a0

File tree

8 files changed

+49
-18
lines changed

8 files changed

+49
-18
lines changed

app-modules/ImportWizard/resources/views/livewire/import-preview-table.blade.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ class="space-y-6"
2626
<span class="font-medium text-info-600 dark:text-info-400" x-text="updates.toLocaleString()"></span>
2727
<span class="text-gray-500 dark:text-gray-400">will be updated</span>
2828
</div>
29+
<template x-if="showCompanyMatch && newCompanies > 0">
30+
<div class="flex items-center gap-1.5">
31+
<span x-show="isProcessing" x-cloak>
32+
<x-filament::loading-indicator class="h-5 w-5 text-warning-500" />
33+
</span>
34+
<span x-show="!isProcessing" x-cloak>
35+
<x-filament::icon icon="heroicon-m-building-office" class="h-5 w-5 text-warning-500" />
36+
</span>
37+
<span class="font-medium text-warning-600 dark:text-warning-400" x-text="newCompanies.toLocaleString()"></span>
38+
<span class="text-gray-500 dark:text-gray-400">new companies</span>
39+
</div>
40+
</template>
2941
</div>
3042
</div>
3143

@@ -64,7 +76,6 @@ class="space-y-6"
6476
<td class="px-3 py-2">
6577
<div class="flex items-center gap-2">
6678
<span class="truncate max-w-[100px] text-gray-950 dark:text-white" x-text="row._company_name || row.company_name || '-'"></span>
67-
<span x-html="getMatchBadge(row._company_match_type || 'none')"></span>
6879
</div>
6980
</td>
7081
</template>

app-modules/ImportWizard/src/Data/ImportSessionData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public function __construct(
2222
public int $processed = 0,
2323
public int $creates = 0,
2424
public int $updates = 0,
25+
public int $newCompanies = 0,
2526
public ?int $heartbeat = null,
2627
public ?string $error = null,
2728
) {}

app-modules/ImportWizard/src/Http/Controllers/PreviewController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function status(string $sessionId): JsonResponse
2929
'processed' => $data->processed,
3030
'creates' => $data->creates,
3131
'updates' => $data->updates,
32+
'newCompanies' => $data->newCompanies,
3233
'total' => $data->total,
3334
],
3435
'hasEnrichedFile' => file_exists(Storage::disk('local')->path("temp-imports/{$sessionId}/enriched.csv")),

app-modules/ImportWizard/src/Jobs/ProcessImportPreview.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ final class ProcessImportPreview implements ShouldQueue
4444
* @param array<string, string> $columnMap
4545
* @param array<string, mixed> $options
4646
* @param array<string, array<string, string>> $valueCorrections
47+
* @param array<string> $initialNewCompanyNames
4748
*/
4849
public function __construct(
4950
public string $sessionId,
@@ -60,6 +61,7 @@ public function __construct(
6061
public int $initialUpdates,
6162
public string $inputHash,
6263
public array $valueCorrections = [],
64+
public array $initialNewCompanyNames = [],
6365
) {
6466
$this->onQueue('imports');
6567
}
@@ -70,6 +72,9 @@ public function handle(PreviewChunkService $service): void
7072
$creates = $this->initialCreates;
7173
$updates = $this->initialUpdates;
7274

75+
// Track unique new company names across all chunks
76+
$newCompanyNames = array_flip($this->initialNewCompanyNames);
77+
7378
// Pre-load records for fast lookups
7479
$recordResolver = app(ImportRecordResolver::class);
7580
$recordResolver->loadForTeam($this->teamId, $this->importerClass);
@@ -110,8 +115,13 @@ public function handle(PreviewChunkService $service): void
110115
$updates += $result['updates'];
111116
$processed += $limit;
112117

118+
// Accumulate unique new company names
119+
foreach ($result['newCompanyNames'] as $companyName) {
120+
$newCompanyNames[$companyName] = true;
121+
}
122+
113123
// Update progress in consolidated cache
114-
$this->updateProgress($processed, $creates, $updates);
124+
$this->updateProgress($processed, $creates, $updates, count($newCompanyNames));
115125
}
116126

117127
// Processing complete - status will be derived as 'ready' since processed >= total
@@ -136,12 +146,13 @@ private function shouldStop(): bool
136146
return $data->inputHash !== $this->inputHash || $data->isHeartbeatStale(self::HEARTBEAT_TIMEOUT_SECONDS);
137147
}
138148

139-
private function updateProgress(int $processed, int $creates, int $updates): void
149+
private function updateProgress(int $processed, int $creates, int $updates, int $newCompanies): void
140150
{
141151
ImportSessionData::update($this->sessionId, [
142152
'processed' => $processed,
143153
'creates' => $creates,
144154
'updates' => $updates,
155+
'new_companies' => $newCompanies,
145156
]);
146157
}
147158

app-modules/ImportWizard/src/Livewire/Concerns/HasImportPreview.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ protected function generateImportPreview(): void
8686
// Store rows for immediate display
8787
$this->previewRows = $firstBatch['rows'];
8888

89+
// Track unique new company names from first batch
90+
$newCompanyNames = $firstBatch['newCompanyNames'];
91+
8992
// Initialize consolidated session cache
9093
new ImportSessionData(
9194
teamId: $teamId,
@@ -94,6 +97,7 @@ protected function generateImportPreview(): void
9497
processed: $initialBatchSize,
9598
creates: $firstBatch['creates'],
9699
updates: $firstBatch['updates'],
100+
newCompanies: count($newCompanyNames),
97101
heartbeat: (int) now()->timestamp,
98102
)->save($this->sessionId);
99103

@@ -124,6 +128,7 @@ protected function generateImportPreview(): void
124128
initialUpdates: $firstBatch['updates'],
125129
inputHash: $newHash,
126130
valueCorrections: $this->valueCorrections,
131+
initialNewCompanyNames: $newCompanyNames,
127132
);
128133
}
129134
}
@@ -147,14 +152,14 @@ public function getPreviewStatus(): PreviewStatus
147152
: PreviewStatus::Pending;
148153
}
149154

150-
/** @return array{processed: int, creates: int, updates: int, total: int} */
155+
/** @return array{processed: int, creates: int, updates: int, newCompanies: int, total: int} */
151156
public function getPreviewProgress(): array
152157
{
153158
$data = $this->sessionId !== null ? ImportSessionData::find($this->sessionId) : null;
154159

155160
return $data instanceof ImportSessionData
156-
? ['processed' => $data->processed, 'creates' => $data->creates, 'updates' => $data->updates, 'total' => $data->total]
157-
: ['processed' => 0, 'creates' => 0, 'updates' => 0, 'total' => $this->rowCount];
161+
? ['processed' => $data->processed, 'creates' => $data->creates, 'updates' => $data->updates, 'newCompanies' => $data->newCompanies, 'total' => $data->total]
162+
: ['processed' => 0, 'creates' => 0, 'updates' => 0, 'newCompanies' => 0, 'total' => $this->rowCount];
158163
}
159164

160165
public function isPreviewReady(): bool

app-modules/ImportWizard/src/Livewire/ImportPreviewTable.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function render(): View
5656
'isReady' => $status === PreviewStatus::Ready,
5757
'creates' => $data !== null ? $data->creates : 0,
5858
'updates' => $data !== null ? $data->updates : 0,
59+
'newCompanies' => $data !== null ? $data->newCompanies : 0,
5960
'processed' => $data !== null ? $data->processed : 0,
6061
'rows' => $this->previewRows,
6162
],

app-modules/ImportWizard/src/Services/PreviewChunkService.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function __construct(
2525
* @param array<string, string> $columnMap
2626
* @param array<string, mixed> $options
2727
* @param array<string, array<string, string>> $valueCorrections
28-
* @return array{rows: array<int, array<string, mixed>>, creates: int, updates: int}
28+
* @return array{rows: array<int, array<string, mixed>>, creates: int, updates: int, newCompanyNames: array<string>}
2929
*/
3030
public function processChunk(
3131
string $importerClass,
@@ -57,6 +57,7 @@ public function processChunk(
5757
$creates = 0;
5858
$updates = 0;
5959
$rows = [];
60+
$newCompanyNames = [];
6061

6162
$rowNumber = $startRow;
6263
foreach ($records as $record) {
@@ -89,6 +90,14 @@ public function processChunk(
8990
// Enrich with company match data for People/Opportunity imports
9091
if ($this->shouldEnrichWithCompanyMatch($importerClass)) {
9192
$formattedRow = $this->enrichRowWithCompanyMatch($formattedRow, $teamId);
93+
94+
// Track unique new company names
95+
if (($formattedRow['_company_match_type'] ?? null) === 'new') {
96+
$companyName = (string) ($formattedRow['_company_name'] ?? '');
97+
if ($companyName !== '') {
98+
$newCompanyNames[$companyName] = true;
99+
}
100+
}
92101
}
93102

94103
// Detect update method
@@ -126,6 +135,7 @@ public function processChunk(
126135
'rows' => $rows,
127136
'creates' => $creates,
128137
'updates' => $updates,
138+
'newCompanyNames' => array_keys($newCompanyNames),
129139
];
130140
}
131141

resources/views/filament/app/import-preview-alpine.blade.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
isReady: config.isReady,
1010
creates: config.creates,
1111
updates: config.updates,
12+
newCompanies: config.newCompanies || 0,
1213
processed: config.processed,
1314
rows: config.rows,
1415
currentRowCount: config.rows.length,
@@ -44,6 +45,7 @@
4445
4546
this.creates = data.progress.creates;
4647
this.updates = data.progress.updates;
48+
this.newCompanies = data.progress.newCompanies || 0;
4749
this.processed = data.progress.processed;
4850
4951
if (data.status === 'ready') {
@@ -109,17 +111,6 @@
109111
return `<svg class='h-5 w-5 text-info-500' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='currentColor'><path fill-rule='evenodd' d='M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z' clip-rule='evenodd'/></svg>`;
110112
}
111113
return '';
112-
},
113-
114-
getMatchBadge(matchType) {
115-
if (matchType === 'id') {
116-
return `<span class='inline-flex items-center rounded-md px-1.5 py-0.5 text-xs font-medium bg-purple-50 text-purple-600 ring-1 ring-inset ring-purple-600/10 dark:bg-purple-400/10 dark:text-purple-400 dark:ring-purple-400/30'>ID</span>`;
117-
} else if (matchType === 'domain') {
118-
return `<span class='inline-flex items-center rounded-md px-1.5 py-0.5 text-xs font-medium bg-green-50 text-green-600 ring-1 ring-inset ring-green-600/10 dark:bg-green-400/10 dark:text-green-400 dark:ring-green-400/30'>Domain</span>`;
119-
} else if (matchType === 'new') {
120-
return `<span class='inline-flex items-center rounded-md px-1.5 py-0.5 text-xs font-medium bg-gray-50 text-gray-600 ring-1 ring-inset ring-gray-600/10 dark:bg-gray-400/10 dark:text-gray-400 dark:ring-gray-400/30'>New</span>`;
121-
}
122-
return `<span class='text-xs text-gray-400'>-</span>`;
123114
}
124115
}));
125116
});

0 commit comments

Comments
 (0)