CSV Import

This commit is contained in:
James Pattinson
2025-10-13 13:28:12 +00:00
parent 9b6a6dab06
commit f721be7280
6 changed files with 1237 additions and 11 deletions

View File

@@ -96,10 +96,16 @@
<span>Click the "Lists" button next to any member to manage their subscriptions</span>
</div>
</div>
<button class="btn btn-primary" id="addMemberBtn">
<i class="fas fa-plus"></i>
Add Member
</button>
<div class="button-group">
<button class="btn btn-primary" id="addMemberBtn">
<i class="fas fa-plus"></i>
Add Member
</button>
<button class="btn btn-secondary" id="showBulkImportBtn">
<i class="fas fa-upload"></i>
Bulk Import CSV
</button>
</div>
</div>
<div class="data-table">
@@ -273,6 +279,189 @@
</div>
</div>
<!-- Bulk Import Modal -->
<div class="modal modal-large" id="bulkImportModal">
<div class="modal-content">
<div class="modal-header">
<h3>Bulk Import Members from CSV</h3>
<button class="modal-close" id="bulkImportModalClose">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<!-- Step 1: File Upload -->
<div class="import-step" id="importStep1">
<h4><i class="fas fa-upload"></i> Step 1: Upload CSV File</h4>
<p class="text-muted">Upload a CSV file containing member information. The file must have 'Name' and 'Email' columns.</p>
<div class="file-upload-area" id="fileUploadArea">
<div class="file-upload-content">
<i class="fas fa-cloud-upload-alt"></i>
<p>Click to select a CSV file or drag and drop</p>
<input type="file" id="csvFileInput" accept=".csv" style="display: none;">
</div>
</div>
<div class="file-info" id="fileInfo" style="display: none;">
<div class="file-details">
<i class="fas fa-file-csv"></i>
<span id="fileName">file.csv</span>
<span id="fileSize" class="text-muted">(0 KB)</span>
</div>
<button type="button" class="btn btn-sm btn-secondary" id="removeFileBtn">
<i class="fas fa-times"></i> Remove
</button>
</div>
<div class="csv-format-help">
<h5><i class="fas fa-info-circle"></i> CSV Format</h5>
<p>Your CSV file should look like this:</p>
<div class="code-example">
<code>Name,Email,Delivery,Member since<br>
Ahmed Ajzan,ahmedajzan@doctors.org.uk,,2025-04-06T18:44:26.819454<br>
Alan Bailey,abgower@icloud.com,,2025-04-06T18:44:26.824446</code>
</div>
<p class="text-muted text-sm">Only the 'Name' and 'Email' columns are required. Additional columns will be ignored.</p>
</div>
</div>
<!-- Step 2: Preview -->
<div class="import-step" id="importStep2" style="display: none;">
<h4><i class="fas fa-eye"></i> Step 2: Preview Data</h4>
<p class="text-muted">Review the data that will be imported:</p>
<div class="preview-stats" id="previewStats">
<div class="stat-item">
<span class="stat-value" id="totalRowsCount">0</span>
<span class="stat-label">Total Rows</span>
</div>
<div class="stat-item">
<span class="stat-value" id="validRowsCount">0</span>
<span class="stat-label">Valid Rows</span>
</div>
<div class="stat-item">
<span class="stat-value" id="errorRowsCount">0</span>
<span class="stat-label">Errors</span>
</div>
</div>
<div class="preview-table-container" id="previewTableContainer">
<table class="table table-sm" id="previewTable">
<thead>
<tr>
<th>Row</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
</thead>
<tbody id="previewTableBody">
<!-- Dynamic content -->
</tbody>
</table>
</div>
<div class="error-list" id="errorList" style="display: none;">
<div class="error-header">
<h5><i class="fas fa-exclamation-triangle"></i> Errors Found</h5>
<button type="button" class="btn btn-sm btn-secondary" id="toggleErrorsBtn">
<span id="errorToggleText">Show All</span>
<i class="fas fa-chevron-down" id="errorToggleIcon"></i>
</button>
</div>
<div class="error-summary" id="errorSummary">
<!-- Summary will be shown here -->
</div>
<div class="error-details" id="errorDetails" style="display: none;">
<div class="error-table-container">
<table class="table table-sm" id="errorTable">
<thead>
<tr>
<th>Row</th>
<th>Issue</th>
<th>Name</th>
<th>Email</th>
<th>Raw Data</th>
</tr>
</thead>
<tbody id="errorTableBody">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Step 3: List Selection -->
<div class="import-step" id="importStep3" style="display: none;">
<h4><i class="fas fa-list"></i> Step 3: Select Mailing Lists</h4>
<p class="text-muted">Choose which mailing lists these members should be subscribed to:</p>
<div class="list-selection" id="listSelection">
<!-- Dynamic content -->
</div>
<div class="selection-info">
<p class="text-muted text-sm">
<i class="fas fa-info-circle"></i>
If a member already exists, they will be added to the selected lists (existing subscriptions will be preserved).
</p>
</div>
</div>
<!-- Step 4: Import Results -->
<div class="import-step" id="importStep4" style="display: none;">
<h4><i class="fas fa-check-circle"></i> Step 4: Import Complete</h4>
<div class="import-results" id="importResults">
<div class="result-stats">
<div class="stat-item">
<span class="stat-value" id="processedCount">0</span>
<span class="stat-label">Processed</span>
</div>
<div class="stat-item">
<span class="stat-value" id="createdCount">0</span>
<span class="stat-label">Created</span>
</div>
<div class="stat-item">
<span class="stat-value" id="updatedCount">0</span>
<span class="stat-label">Updated</span>
</div>
<div class="stat-item">
<span class="stat-value" id="subscriptionsCount">0</span>
<span class="stat-label">Subscriptions</span>
</div>
</div>
<div class="result-errors" id="resultErrors" style="display: none;">
<h5><i class="fas fa-exclamation-triangle"></i> Import Errors</h5>
<ul id="resultErrorList">
<!-- Dynamic content -->
</ul>
</div>
</div>
</div>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" id="bulkImportBackBtn" style="display: none;">
<i class="fas fa-arrow-left"></i> Back
</button>
<button type="button" class="btn btn-secondary" id="bulkImportCancelBtn">Cancel</button>
<button type="button" class="btn btn-primary" id="bulkImportNextBtn" disabled>
Next <i class="fas fa-arrow-right"></i>
</button>
<button type="button" class="btn btn-primary" id="bulkImportBtn" style="display: none;">
<i class="fas fa-upload"></i> Import Members
</button>
<button type="button" class="btn btn-success" id="bulkImportDoneBtn" style="display: none;">
<i class="fas fa-check"></i> Done
</button>
</div>
</div>
</div>
<!-- Confirmation Modal -->
<div class="modal" id="confirmModal">
<div class="modal-content">