Appearance
Bulk Device Registration Component Documentation
File: src/pages/private/admin/devices/bulkDevice.svelte
Overview
This component enables bulk registration of Headset devices by automatically generating sequential device names when scanning multiple QR codes. It maintains state between device registrations to streamline the bulk addition process.
Component Script
Props
ts
export let qrCodeUrl: string = ""; // URL for generated QR code
export let loading: boolean = false; // Loading state
export let regRef: string = ""; // Registration reference tokenState Variables
ts
let deviceName: string = ""; // Base device name input
let notes: string = ""; // Device notes input
let unsubscribe: { unsubscribe: () => void } | null = null; // Subscription cleanup
let deviceCount: number = 0; // Counter for sequential namingLifecycle Methods
ts
onMount(() => {
// Subscribe to device addition events
const client = getClient();
const token = get(accessToken);
const subscription$ = client.subscription(DEVICE_ADDED_SUBSCRIPTION, { token });
unsubscribe = subscribe((result) => {
if (result.data?.onDeviceAdded?.deviceRefToken === regRef) {
// Extract base name and current number from device name
const match = deviceName.match(/(.*?)(\d+)$/);
const baseName = match ? match[1].trim() : deviceName.trim();
const currentNumber = match ? parseInt(match[2]) : 0;
// Increment counter and update name
deviceCount = currentNumber + 1;
deviceName = `${baseName} ${deviceCount}`.trim();
// Trigger next generation
dispatch("submit", { name: deviceName, notes });
}
})(subscription$);
});
onDestroy(() => {
// Clean up subscription
if (unsubscribe?.unsubscribe) {
unsubscribe.unsubscribe();
}
});Event Handlers
ts
function handleSubmit() {
// Trigger QR code generation
dispatch("submit", { name: deviceName, notes });
}UI Structure
svelte
<div class="p-6 w-full">
<form on:submit|preventDefault={handleSubmit} class="flex gap-4 w-full">
<!-- Left Column: Form Inputs -->
<div class="flex flex-col gap-4 w-full">
<!-- Device Name Input -->
<div>
<label for="deviceName">Device Name</label>
<input
id="deviceName"
type="text"
bind:value={deviceName}
placeholder="Enter base device name"
required
/>
</div>
<!-- Notes Textarea -->
<div>
<label for="notes">Notes</label>
<textarea
id="notes"
bind:value={notes}
placeholder="Enter notes for all devices"
rows={8}
></textarea>
</div>
</div>
<!-- Right Column: QR Code Generation -->
<div class="w-[700px]">
<label for="qrCode">QR Code</label>
<div class="flex flex-col items-center space-y-2 p-4 border-2 border-dashed border-gray-300 rounded-md">
{#if loading}
<!-- Loading state -->
<div class="flex-grow grid place-content-center my-3 py-3 h-[175px]">
<Chasing />
</div>
{:else if qrCodeUrl}
<!-- QR Code display -->
<img src={qrCodeUrl} alt="Device QR Code" />
<p class="text-sm text-gray-500">
Scanning this will add device: {deviceName}
</p>
{:else}
<!-- Empty state -->
<div class="text-center p-8">
<!-- Placeholder icon -->
<p class="mt-2 text-sm text-gray-500">QR Code</p>
</div>
{/if}
</div>
<button type="submit">Generate</button>
</div>
</form>
</div>Key Features
Sequential Naming:
- Automatically increments device numbers (e.g., "Device 1", "Device 2")
- Maintains base name while updating counter
Continuous Registration:
- Automatically generates next QR code after successful scan
- Maintains notes and base name between registrations
Real-time Feedback:
- Shows which device name will be registered next
- Clear visual states for loading/empty/active QR codes
Bulk Optimization:
- Single form submission for multiple devices
- Persistent notes apply to all devices in batch
Events
| Event Name | Description | Payload |
|---|---|---|
submit | Trigger QR code generation | { name: string, notes: string } |
Usage Example
svelte
<script>
import BulkDevice from "./bulkDevice.svelte";
let qrCode = "";
let loading = false;
let regRef = "";
function handleBulkSubmit({ detail }) {
// Call API to generate QR code
loading = true;
generateBulkDeviceQR(detail.name, detail.notes)
.then(result => {
qrCode = result.qrCodeUrl;
regRef = result.regRef;
})
.finally(() => loading = false);
}
</script>
<BulkDevice
bind:qrCodeUrl={qrCode}
bind:loading
bind:regRef
on:submit={handleBulkSubmit}
/>Styling Notes
- Two-column layout: Form inputs on left, QR code on right
- Consistent styling: Matches single device form for familiarity
- Clear visual states: Distinct UI for loading/empty/active states
- Responsive: Adapts to container width while maintaining readability
Error Handling
- Automatic subscription cleanup on component destruction
- Required field validation for device name
- Loading states prevent duplicate submissions