fix: add missing each-block keys (svelte/require-each-key)

Fixed all 27 remaining instances across 19 files. Keys used:
- Object ID fields where available (e.g. account_id_random, event_file_id)
- index for logger lists with no reliable unique key
- Property name for Object.entries() loops
This commit is contained in:
Scott Idem
2026-03-06 17:54:50 -05:00
parent dd5cf9b63b
commit 48d5fe8995
19 changed files with 163 additions and 163 deletions

View File

@@ -12,9 +12,9 @@
let qry_str = $state('');
let filtered_li = $derived(
qry_str
? account_li.filter(a =>
a.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
qry_str
? account_li.filter(a =>
a.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
a.code?.toLowerCase().includes(qry_str.toLowerCase())
)
: account_li
@@ -40,7 +40,7 @@
if (!name) return;
const code = prompt('Enter account code (optional):');
const new_acct = await create_ae_obj__account({
api_cfg: $ae_api,
data_kv: {
@@ -81,11 +81,11 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Search by name or code..."
type="search"
bind:value={qry_str}
placeholder="Search by name or code..."
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_accounts} disabled={loading}>
{#if loading}
@@ -138,7 +138,7 @@
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each filtered_li as acct}
{#each filtered_li as acct (acct.account_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="absolute top-4 right-4 flex gap-1">
{#if acct.hide}
@@ -158,7 +158,7 @@
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {acct.code || '--'}</p>
</div>
</header>
<div class="space-y-2 text-xs opacity-70">
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
<Calendar size={14} class="text-primary-500 shrink-0" />

View File

@@ -18,7 +18,7 @@
async function load_logs() {
if (!$ae_loc.account_id) return;
loading = true;
const results = await qry__activity_log({
api_cfg: $ae_api,
account_id: $ae_loc.account_id,
@@ -77,11 +77,11 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Action, name, description..."
type="search"
bind:value={qry_str}
placeholder="Action, name, description..."
/>
<button type="submit" class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" disabled={loading}>
<span class="whitespace-nowrap tracking-wide">Search</span>
@@ -131,7 +131,7 @@
</tr>
</thead>
<tbody>
{#each log_li as log}
{#each log_li as log, index (index)}
<tr class="transition-colors text-sm">
<!-- Date/Time -->
<td class="whitespace-nowrap">

View File

@@ -11,9 +11,9 @@
let show_add_form = $state(false);
let qry_str = $state('');
let filtered_li: any[] = $derived(
qry_str
? address_li.filter(a =>
a.city?.toLowerCase().includes(qry_str.toLowerCase()) ||
qry_str
? address_li.filter(a =>
a.city?.toLowerCase().includes(qry_str.toLowerCase()) ||
a.state_province?.toLowerCase().includes(qry_str.toLowerCase()) ||
a.organization_name?.toLowerCase().includes(qry_str.toLowerCase()) ||
a.line_1?.toLowerCase().includes(qry_str.toLowerCase())
@@ -51,8 +51,8 @@
</div>
<h1 class="h2 font-black tracking-tight">Address Management</h1>
</div>
<button
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
<button
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
onclick={() => show_add_form = !show_add_form}
>
{#if show_add_form}
@@ -65,7 +65,7 @@
{#if show_add_form}
<div class="animate-fade-in">
<Address_form
<Address_form
onSave={(new_addr) => {
show_add_form = false;
load_addresses();
@@ -85,11 +85,11 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Search by city, state, organization, or street..."
type="search"
bind:value={qry_str}
placeholder="Search by city, state, organization, or street..."
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_addresses} disabled={loading}>
{#if loading}
@@ -119,9 +119,9 @@
Linked Addresses
<span class="badge variant-soft-secondary ml-auto">{filtered_li.length} entries</span>
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each filtered_li as addr}
{#each filtered_li as addr (addr.address_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="absolute top-4 right-4">
<span class="badge {addr.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">

View File

@@ -74,7 +74,7 @@
</tr>
</thead>
<tbody>
{#each $lq_kv__person_obj_li as person_obj}
{#each $lq_kv__person_obj_li as person_obj (person_obj.person_id_random)}
<tr class:dim={person_obj?.hide}>
<td class="px-4 py-2">
<span class="fas fa-user"></span>

View File

@@ -9,9 +9,9 @@
let contact_li: any[] = $state([]);
let qry_str = $state('');
let filtered_li: any[] = $derived(
qry_str
? contact_li.filter(c =>
c.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
qry_str
? contact_li.filter(c =>
c.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
c.title?.toLowerCase().includes(qry_str.toLowerCase()) ||
c.email?.toLowerCase().includes(qry_str.toLowerCase()) ||
c.phone_office?.toLowerCase().includes(qry_str.toLowerCase())
@@ -51,8 +51,8 @@
</div>
<h1 class="h2 font-black tracking-tight">Contact Management</h1>
</div>
<button
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
<button
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
onclick={() => show_add_form = !show_add_form}
>
{#if show_add_form}
@@ -65,7 +65,7 @@
{#if show_add_form}
<div class="animate-fade-in">
<Contact_form
<Contact_form
onSave={(new_con) => {
show_add_form = false;
load_contacts();
@@ -85,11 +85,11 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Search by name, title, email, or phone..."
type="search"
bind:value={qry_str}
placeholder="Search by name, title, email, or phone..."
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_contacts} disabled={loading}>
{#if loading}
@@ -121,7 +121,7 @@
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each filtered_li as con}
{#each filtered_li as con (con.contact_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="absolute top-4 right-4">
<span class="badge {con.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
@@ -138,7 +138,7 @@
<p class="text-[10px] uppercase font-bold opacity-50 truncate">{con.title || 'Support Contact'}</p>
</div>
</header>
<div class="space-y-2 text-xs opacity-70">
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
<Mail size={14} class="text-primary-500 shrink-0" />

View File

@@ -19,11 +19,11 @@
const [countries, subdivisions, time_zones] = await Promise.all([
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country', log_lvl: 1 }),
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country_subdivision', log_lvl: 1 }),
api.get_ae_obj_li_for_lu({
api_cfg: $ae_api,
for_lu_type: 'time_zone',
api.get_ae_obj_li_for_lu({
api_cfg: $ae_api,
for_lu_type: 'time_zone',
only_priority: tz_only_priority,
log_lvl: 1
log_lvl: 1
})
]);
@@ -91,7 +91,7 @@
Country Reference
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.countries.length} Records</span>
</h3>
<div class="table-container max-h-[400px] overflow-auto border border-surface-500/10 rounded-lg">
<table class="table table-hover table-compact">
<thead>
@@ -101,7 +101,7 @@
</tr>
</thead>
<tbody>
{#each lookups.countries as c}
{#each lookups.countries as c (c.alpha_2_code)}
<tr class="transition-colors">
<td class="font-bold">{c.name || c.english_short_name}</td>
<td class="text-center"><span class="badge variant-soft-surface font-mono text-primary-500">{c.alpha_2_code}</span></td>
@@ -119,7 +119,7 @@
Country Subdivisions (States/Provinces)
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.subdivisions.length} Records</span>
</h3>
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
<table class="table table-hover table-compact">
<thead>
@@ -130,7 +130,7 @@
</tr>
</thead>
<tbody>
{#each lookups.subdivisions as s}
{#each lookups.subdivisions as s, i (i)}
<tr class="transition-colors">
<td class="opacity-60">{s.country_alpha_2_code}</td>
<td class="font-bold">{s.name}</td>
@@ -150,7 +150,7 @@
Time Zone Reference
<span class="badge variant-soft-secondary text-[10px] uppercase font-bold">{lookups.time_zones.length} Zones</span>
</h3>
<button
<button
class="btn btn-sm transition-all {tz_only_priority ? 'variant-filled-warning' : 'variant-soft-surface'}"
onclick={toggle_tz_priority}
disabled={loading}
@@ -159,7 +159,7 @@
{tz_only_priority ? 'Showing Priority' : 'Show Only Priority'}
</button>
</div>
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
<table class="table table-hover table-compact">
<thead>
@@ -169,7 +169,7 @@
</tr>
</thead>
<tbody>
{#each lookups.time_zones as tz}
{#each lookups.time_zones as tz (tz.name)}
<tr class="transition-colors">
<td class="font-bold">{tz.name}</td>
<td class="text-right"><span class="badge variant-soft-surface font-mono">{tz.offset_seconds / 3600}h</span></td>

View File

@@ -289,7 +289,7 @@
<p class="text-center py-4 italic opacity-60 border border-dashed border-surface-500/30">No unlinked user accounts found.</p>
{:else}
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
{#each available_users as user}
{#each available_users as user (user.user_id)}
<button
class="card p-3 variant-soft-primary hover:variant-filled-primary text-left transition-all flex flex-col gap-1"
onclick={() => handle_link_user(user.user_id)}
@@ -335,7 +335,7 @@
<p class="text-sm italic opacity-50">No related events found.</p>
{:else}
<div class="space-y-2">
{#each related_events as ev}
{#each related_events as ev (ev.event_id)}
<a href="/events/{ev.event_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
<span class="font-bold text-sm">{ev.name}</span>
<span class="text-[10px] opacity-60">{new Date(ev.start_datetime).toLocaleDateString()}</span>
@@ -356,7 +356,7 @@
<p class="text-sm italic opacity-50">No related posts found.</p>
{:else}
<div class="space-y-2">
{#each related_posts as post}
{#each related_posts as post (post.post_id)}
<a href="/idaa/bb/{post.post_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
<span class="font-bold text-sm">{post.title}</span>
<div class="flex justify-between items-center text-[10px] opacity-60">
@@ -380,7 +380,7 @@
<p class="text-sm italic opacity-50">No recent activity logs.</p>
{:else}
<div class="space-y-2">
{#each related_activity_logs as log}
{#each related_activity_logs as log, index (index)}
<div class="card p-3 variant-soft flex flex-col gap-1">
<div class="flex justify-between items-start gap-2">
<span class="badge variant-filled-surface text-[9px] uppercase tracking-tighter">{log.action}</span>

View File

@@ -12,9 +12,9 @@
let qry_str = $state('');
let filtered_li = $derived(
qry_str
? site_li.filter(s =>
s.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
qry_str
? site_li.filter(s =>
s.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
s.code?.toLowerCase().includes(qry_str.toLowerCase())
)
: site_li
@@ -42,7 +42,7 @@
if (!name) return;
const code = prompt('Enter site code (optional):');
const new_site = await create_ae_obj__site({
api_cfg: $ae_api,
account_id: $ae_loc.account_id,
@@ -84,11 +84,11 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Search by name or code..."
type="search"
bind:value={qry_str}
placeholder="Search by name or code..."
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_sites} disabled={loading}>
{#if loading}
@@ -141,7 +141,7 @@
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each filtered_li as site}
{#each filtered_li as site (site.site_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="absolute top-4 right-4 flex gap-1">
{#if site.hide}
@@ -161,7 +161,7 @@
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {site.code || '--'}</p>
</div>
</header>
<div class="space-y-2 text-xs opacity-70">
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
<Calendar size={14} class="text-primary-500 shrink-0" />

View File

@@ -166,9 +166,9 @@
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
<Database size={18} class="text-warning-500" /> Site Settings (cfg_json)
</h3>
<AE_Comp_Site_Config_Editor
bind:cfg_json={site.cfg_json}
on_save={handle_save_site}
<AE_Comp_Site_Config_Editor
bind:cfg_json={site.cfg_json}
on_save={handle_save_site}
/>
</div>
@@ -207,7 +207,7 @@
<p class="text-sm opacity-60 text-center py-8 bg-surface-500/5 rounded-lg border-2 border-dashed border-surface-500/20">No domains configured.</p>
{:else}
<div class="space-y-3">
{#each domain_li as dom}
{#each domain_li as dom (dom.site_domain_id_random)}
<div class="card p-3 variant-soft shadow-sm border border-surface-500/10 flex justify-between items-center group">
<div class="flex flex-col">
<span class="font-bold text-sm flex items-center gap-1">

View File

@@ -14,7 +14,7 @@
async function load_users() {
loading = true;
let for_obj_id: string | null = $ae_loc.account_id;
let include_global = true;
@@ -48,7 +48,7 @@
const username = prompt('Enter new username:');
if (!username) return;
const email = prompt('Enter email address:');
// Link to account if scope is 'account' or 'all', otherwise create global user
const account_id = qry_account_scope === 'global' ? undefined : $ae_loc.account_id;
@@ -87,12 +87,12 @@
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
<Search size={18} class="opacity-50" />
</div>
<input
<input
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
type="search"
bind:value={qry_str}
placeholder="Search username or email..."
onkeydown={(e) => e.key === 'Enter' && load_users()}
type="search"
bind:value={qry_str}
placeholder="Search username or email..."
onkeydown={(e) => e.key === 'Enter' && load_users()}
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_users} disabled={loading}>
{#if loading}
@@ -145,7 +145,7 @@
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each user_li as user}
{#each user_li as user (user.user_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group">
<header class="flex justify-between items-start">
<div class="flex items-center gap-3">
@@ -174,7 +174,7 @@
{/if}
</div>
</header>
<div class="space-y-2">
<div class="flex items-center gap-2 text-xs opacity-70 bg-black/5 p-2 rounded-lg">
<Mail size={14} class="text-primary-500" />