feat(pres_mgmt): automate Session POC loading and enhance field editor UX

- Updated Element_ae_obj_field_editor_new.svelte with on_open callback support.
- Improved Select field UX in the editor with an inline loading spinner when options are empty.
- Streamlined session_view.svelte by using on_open to trigger person record loading automatically.
- Removed redundant manual 'Select Person' button in favor of automated lazy-loading.
This commit is contained in:
Scott Idem
2026-06-16 18:14:14 -04:00
parent 8146316aaf
commit d23f9073c4
2 changed files with 61 additions and 52 deletions

View File

@@ -155,7 +155,6 @@ function coerce_select_value(raw: string, reference: T): any {
} }
// Internal State // Internal State
// is_editing is a $bindable prop (declared above) — not a local $state.
let patch_status = $state<'idle' | 'processing' | 'success' | 'error'>('idle'); let patch_status = $state<'idle' | 'processing' | 'success' | 'error'>('idle');
let error_message = $state(''); let error_message = $state('');
let draft_value = $state(to_input_value(current_value, field_type)); let draft_value = $state(to_input_value(current_value, field_type));
@@ -244,6 +243,7 @@ function toggle_edit() {
has_optimistic = false; has_optimistic = false;
draft_value = to_input_value(current_value, field_type); draft_value = to_input_value(current_value, field_type);
is_editing = true; is_editing = true;
if (on_open) on_open();
} }
} }
@@ -329,19 +329,29 @@ function handle_keydown(e: KeyboardEvent) {
class="textarea" class="textarea"
{placeholder}></textarea> {placeholder}></textarea>
{:else if field_type === 'select'} {:else if field_type === 'select'}
<div class="relative">
<select <select
{id} {id}
bind:this={input_ref} bind:this={input_ref}
value={draft_value} value={draft_value}
onchange={(e) => draft_value = coerce_select_value(e.currentTarget.value, current_value)} onchange={(e) => draft_value = coerce_select_value(e.currentTarget.value, current_value)}
class="select"> class="select pr-10">
{#if allow_null} {#if allow_null}
<option value={null}>-- None --</option> <option value={null}>-- None --</option>
{/if} {/if}
{#if Object.keys(select_options).length === 0}
<option value="" disabled>Loading options...</option>
{/if}
{#each Object.entries(select_options) as [val, label] (val)} {#each Object.entries(select_options) as [val, label] (val)}
<option value={val}>{label}</option> <option value={val}>{label}</option>
{/each} {/each}
</select> </select>
{#if Object.keys(select_options).length === 0}
<div class="absolute inset-y-0 right-8 flex items-center">
<LoaderCircle size="14" class="animate-spin opacity-50" />
</div>
{/if}
</div>
{:else if field_type === 'checkbox'} {:else if field_type === 'checkbox'}
<label class="flex items-center space-x-2"> <label class="flex items-center space-x-2">
<input <input

View File

@@ -109,6 +109,9 @@ function to_datetime_local(raw: string | Date | null | undefined): string {
// a session POC from known person records instead of typing IDs manually. // a session POC from known person records instead of typing IDs manually.
async function load_person_options_for_session_poc() { async function load_person_options_for_session_poc() {
if (!$slct.account_id) return; if (!$slct.account_id) return;
// Don't reload if already loaded or loading
if (Object.keys($slct.person_obj_kv ?? {}).length > 1) return;
$slct.person_obj_li = core_func $slct.person_obj_li = core_func
.load_ae_obj_li__person({ .load_ae_obj_li__person({
api_cfg: $ae_api, api_cfg: $ae_api,
@@ -568,12 +571,11 @@ async function send_poc_email_link() {
{/if} {/if}
<!-- POC person selector — trusted staff in edit_mode only. <!-- POC person selector — trusted staff in edit_mode only.
WHY: Only show the select editor after "Select Person" loads the list. WHY: Automatically load person list when editor opens via on_open.
Showing an empty dropdown on editor open was confusing staff. Eliminates the previous manual \"Select Person\" step.
person_options_loaded gates rendering until the list is ready. --> The editor now shows a loading state if options are empty. -->
{#if $ae_loc.trusted_access && $ae_loc.edit_mode} {#if $ae_loc.trusted_access && $ae_loc.edit_mode}
<div class="mt-1 flex flex-wrap items-center gap-2"> <div class="mt-1 flex flex-wrap items-center gap-2">
{#if person_options_loaded}
<Element_ae_obj_field_editor <Element_ae_obj_field_editor
object_type="event_session" object_type="event_session"
object_id={$lq__event_session_obj.id} object_id={$lq__event_session_obj.id}
@@ -583,6 +585,7 @@ async function send_poc_email_link() {
current_value={$lq__event_session_obj.poc_person_id ?? null} current_value={$lq__event_session_obj.poc_person_id ?? null}
select_options={$slct.person_obj_kv} select_options={$slct.person_obj_kv}
allow_null={$ae_loc.administrator_access} allow_null={$ae_loc.administrator_access}
on_open={load_person_options_for_session_poc}
on_success={() => on_success={() =>
events_func.load_ae_obj_id__event_session({ events_func.load_ae_obj_id__event_session({
api_cfg: $ae_api, api_cfg: $ae_api,
@@ -603,17 +606,13 @@ async function send_poc_email_link() {
</span> </span>
{/if} {/if}
</Element_ae_obj_field_editor> </Element_ae_obj_field_editor>
{/if}
<button <button
type="button" type="button"
onclick={load_person_options_for_session_poc} onclick={load_person_options_for_session_poc}
class="btn btn-sm preset-tonal-warning group"> class="btn btn-sm preset-tonal-surface group opacity-40 hover:opacity-100"
<!-- <Pencil size="1em" class="" /> --> title="Force refresh person list">
<RefreshCw size="1em" class="text-xs" /> <RefreshCw size="1em" class="text-xs" />
<span class="hidden group-hover:inline-block">
{person_options_loaded ? 'Refresh' : 'Select Person'}
</span>
</button> </button>
</div> </div>
{/if} {/if}