leads: lead detail UX overhaul — notes editor, priority star, profile card cleanup
- Replace admin field editor with direct TipTap + Save Notes button for exhibitor notes; show Add Notes button when notes are empty (no dead placeholder) - Add one-click priority star toggle in header (always visible, no edit mode required) - Remove Exhibit Context card (exhibitors don't need to see their own booth name) - Move Captured By into profile card with human-readable labels (shared_passcode → "Booth (Shared)", access type codes → Staff/Admin) - Add location row (city/state + country) to profile card - Gate Remove button to edit mode only to prevent accidental taps - Fix button position stability: Edit/View always rightmost (same screen position), Remove grows in from left — prevents double-tap accidents - Add unsaved-changes guard (beforeNavigate) covering both notes and custom question form - Custom questions form: hide Save when no questions configured, show "Configure in Manage Tab" link instead Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,13 +4,12 @@
|
|||||||
* Lead Detail View - Basic Read-Only version.
|
* Lead Detail View - Basic Read-Only version.
|
||||||
*/
|
*/
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { goto } from '$app/navigation';
|
import { beforeNavigate, goto } from '$app/navigation';
|
||||||
import { liveQuery } from 'dexie';
|
import { liveQuery } from 'dexie';
|
||||||
import { db_events } from '$lib/ae_events/db_events';
|
import { db_events } from '$lib/ae_events/db_events';
|
||||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||||
import Element_ae_obj_field_editor from '$lib/elements/element_ae_obj_field_editor.svelte';
|
|
||||||
import AE_Comp_Editor_TipTap from '$lib/elements/element_editor_tiptap.svelte';
|
import AE_Comp_Editor_TipTap from '$lib/elements/element_editor_tiptap.svelte';
|
||||||
import Comp_lead_detail_form from './ae_comp__lead_detail_form.svelte';
|
import Comp_lead_detail_form from './ae_comp__lead_detail_form.svelte';
|
||||||
import {
|
import {
|
||||||
@@ -29,9 +28,9 @@ import {
|
|||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
SquarePen,
|
SquarePen,
|
||||||
Star,
|
Star,
|
||||||
Store,
|
|
||||||
Trash2,
|
Trash2,
|
||||||
User
|
User,
|
||||||
|
UserCheck
|
||||||
} from '@lucide/svelte';
|
} from '@lucide/svelte';
|
||||||
const exhibit_tracking_id = $derived(page.params.exhibit_tracking_id);
|
const exhibit_tracking_id = $derived(page.params.exhibit_tracking_id);
|
||||||
|
|
||||||
@@ -52,6 +51,51 @@ let lq__exhibit_obj = $derived(
|
|||||||
|
|
||||||
let is_edit_mode = $state(false);
|
let is_edit_mode = $state(false);
|
||||||
|
|
||||||
|
// Priority toggle — one-click, saves immediately without entering edit mode.
|
||||||
|
let priority_saving = $state(false);
|
||||||
|
async function toggle_priority() {
|
||||||
|
if (!exhibit_tracking_id || priority_saving) return;
|
||||||
|
priority_saving = true;
|
||||||
|
try {
|
||||||
|
await events_func.update_ae_obj__exhibit_tracking({
|
||||||
|
api_cfg: $ae_api,
|
||||||
|
exhibit_id: page.params.exhibit_id ?? '',
|
||||||
|
exhibit_tracking_id,
|
||||||
|
data: { priority: !$lq__lead_obj?.priority }
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
priority_saving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Human-readable label for external_person_id.
|
||||||
|
// Raw values: 'shared_passcode' (booth shared login), an email (licensed user),
|
||||||
|
// or an Aether access_type string (trusted/administrator — staff bypass).
|
||||||
|
function format_captured_by(id: string | null | undefined): string {
|
||||||
|
if (!id) return 'Unknown';
|
||||||
|
if (id === 'shared_passcode') return 'Booth (Shared)';
|
||||||
|
if (id.includes('@')) return id;
|
||||||
|
const map: Record<string, string> = {
|
||||||
|
trusted: 'Staff',
|
||||||
|
administrator: 'Admin',
|
||||||
|
edit_mode: 'Staff'
|
||||||
|
};
|
||||||
|
return map[id] ?? id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsaved-changes guard — warn before navigating away if notes or responses are dirty.
|
||||||
|
let form_is_dirty = $state(false);
|
||||||
|
beforeNavigate(({ cancel }) => {
|
||||||
|
const notes_dirty =
|
||||||
|
is_edit_mode &&
|
||||||
|
draft_notes !== ($lq__lead_obj?.exhibitor_notes ?? '');
|
||||||
|
if (notes_dirty || form_is_dirty) {
|
||||||
|
if (!confirm('You have unsaved changes. Leave without saving?')) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Notes editing state
|
// Notes editing state
|
||||||
let draft_notes = $state('');
|
let draft_notes = $state('');
|
||||||
let notes_status = $state<'idle' | 'saving' | 'success' | 'error'>('idle');
|
let notes_status = $state<'idle' | 'saving' | 'success' | 'error'>('idle');
|
||||||
@@ -151,6 +195,58 @@ function format_date(date: any) {
|
|||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{#if $lq__lead_obj}
|
{#if $lq__lead_obj}
|
||||||
|
<!-- Remove — leftmost so it never lands on top of Edit/View when it appears.
|
||||||
|
Only shown in edit mode; soft-delete only (enable=false), recoverable. -->
|
||||||
|
{#if is_edit_mode && $lq__lead_obj.enable}
|
||||||
|
{#if remove_status === 'confirm'}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-filled-error font-bold"
|
||||||
|
onclick={remove_lead}>
|
||||||
|
<Trash2 size="1em" />
|
||||||
|
Confirm?
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-outlined-surface"
|
||||||
|
onclick={() => (remove_status = 'idle')}>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-outlined-error"
|
||||||
|
disabled={remove_status === 'removing'}
|
||||||
|
onclick={() => (remove_status = 'confirm')}>
|
||||||
|
{#if remove_status === 'removing'}
|
||||||
|
<LoaderCircle size="1em" class="animate-spin" />
|
||||||
|
{:else}
|
||||||
|
<Trash2 size="1em" />
|
||||||
|
{/if}
|
||||||
|
<span class="hidden sm:inline">Remove</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- Priority toggle — always visible, one-click, no edit mode needed. -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm font-bold transition-all"
|
||||||
|
class:preset-filled-warning={$lq__lead_obj.priority}
|
||||||
|
class:preset-outlined-surface={!$lq__lead_obj.priority}
|
||||||
|
class:opacity-40={!$lq__lead_obj.priority}
|
||||||
|
disabled={priority_saving}
|
||||||
|
onclick={toggle_priority}
|
||||||
|
title={$lq__lead_obj.priority ? 'Remove priority flag' : 'Mark as priority lead'}>
|
||||||
|
{#if priority_saving}
|
||||||
|
<LoaderCircle size="1em" class="animate-spin" />
|
||||||
|
{:else}
|
||||||
|
<Star size="1em" class={$lq__lead_obj.priority ? 'fill-current' : ''} />
|
||||||
|
{/if}
|
||||||
|
<span class="hidden sm:inline">Priority</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Edit/View — always rightmost so its position never shifts. -->
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm"
|
class="btn btn-sm"
|
||||||
class:preset-filled-primary={is_edit_mode}
|
class:preset-filled-primary={is_edit_mode}
|
||||||
@@ -160,51 +256,11 @@ function format_date(date: any) {
|
|||||||
remove_status = 'idle';
|
remove_status = 'idle';
|
||||||
}}>
|
}}>
|
||||||
{#if is_edit_mode}
|
{#if is_edit_mode}
|
||||||
<Eye size="1.2em" class="mr-1" /> View
|
<Eye size="1.2em" /> <span class="hidden sm:inline ml-1">View</span>
|
||||||
{:else}
|
{:else}
|
||||||
<SquarePen size="1.2em" class="mr-1" /> Edit
|
<SquarePen size="1.2em" /> <span class="hidden sm:inline ml-1">Edit</span>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Remove Lead — two-click confirm to prevent accidental removal.
|
|
||||||
Removing only sets enable=false (soft-delete); the record can be restored. -->
|
|
||||||
{#if $lq__lead_obj.enable}
|
|
||||||
{#if remove_status === 'confirm'}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm preset-filled-error font-bold"
|
|
||||||
onclick={remove_lead}>
|
|
||||||
<Trash2 size="1em" />
|
|
||||||
Confirm Remove?
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm preset-outlined-surface opacity-60"
|
|
||||||
onclick={() => (remove_status = 'idle')}
|
|
||||||
>Cancel</button>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm preset-outlined-error opacity-70"
|
|
||||||
disabled={remove_status === 'removing'}
|
|
||||||
onclick={() => (remove_status = 'confirm')}>
|
|
||||||
{#if remove_status === 'removing'}
|
|
||||||
<LoaderCircle size="1em" class="animate-spin" />
|
|
||||||
{:else}
|
|
||||||
<Trash2 size="1em" />
|
|
||||||
{/if}
|
|
||||||
Remove
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if $lq__lead_obj?.priority}
|
|
||||||
<span
|
|
||||||
class="badge preset-filled-warning flex items-center gap-1 font-bold">
|
|
||||||
<Star size="1em" class="mr-1" />
|
|
||||||
Priority
|
|
||||||
</span>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -258,6 +314,15 @@ function format_date(date: any) {
|
|||||||
$lq__lead_obj.event_badge_affiliations_override}</span>
|
$lq__lead_obj.event_badge_affiliations_override}</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $lq__lead_obj.event_badge_location_override || $lq__lead_obj.event_badge_location || $lq__lead_obj.event_badge_country}
|
||||||
|
<div class="flex items-center gap-2 text-sm opacity-70">
|
||||||
|
<MapPin size="1em" class="flex-none opacity-60" />
|
||||||
|
<span>{[
|
||||||
|
$lq__lead_obj.event_badge_location_override || $lq__lead_obj.event_badge_location,
|
||||||
|
$lq__lead_obj.event_badge_country
|
||||||
|
].filter(Boolean).join(', ')}</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-2 text-sm opacity-70">
|
class="flex items-center gap-2 text-sm opacity-70">
|
||||||
<a href={`mailto:${$lq__lead_obj.event_badge_email}`}
|
<a href={`mailto:${$lq__lead_obj.event_badge_email}`}
|
||||||
@@ -282,6 +347,11 @@ function format_date(date: any) {
|
|||||||
)}</span>
|
)}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-2 text-sm opacity-60">
|
||||||
|
<UserCheck size="1em" class="flex-none" />
|
||||||
|
<span>Captured by {format_captured_by($lq__lead_obj.external_person_id)}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -300,10 +370,12 @@ function format_date(date: any) {
|
|||||||
<Comp_lead_detail_form
|
<Comp_lead_detail_form
|
||||||
exhibit_tracking_id={exhibit_tracking_id ?? ''}
|
exhibit_tracking_id={exhibit_tracking_id ?? ''}
|
||||||
exhibit_id={page.params.exhibit_id ?? ''}
|
exhibit_id={page.params.exhibit_id ?? ''}
|
||||||
|
event_id={page.params.event_id ?? ''}
|
||||||
custom_questions_json={$lq__exhibit_obj?.leads_custom_questions_json ??
|
custom_questions_json={$lq__exhibit_obj?.leads_custom_questions_json ??
|
||||||
'[]'}
|
'[]'}
|
||||||
current_responses_json={$lq__lead_obj.responses_json ??
|
current_responses_json={$lq__lead_obj.responses_json ??
|
||||||
'{}'} />
|
'{}'}
|
||||||
|
bind:is_dirty={form_is_dirty} />
|
||||||
{:else if $lq__lead_obj.responses_json}
|
{:else if $lq__lead_obj.responses_json}
|
||||||
{@const responses =
|
{@const responses =
|
||||||
typeof $lq__lead_obj.responses_json === 'string'
|
typeof $lq__lead_obj.responses_json === 'string'
|
||||||
@@ -412,52 +484,8 @@ function format_date(date: any) {
|
|||||||
|
|
||||||
<!-- Right: Metadata & Stats -->
|
<!-- Right: Metadata & Stats -->
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<!-- exhibit association -->
|
<!-- System Audit — staff/admin only; end users don't need raw IDs. -->
|
||||||
<div
|
{#if $ae_loc.manager_access}
|
||||||
class="card bg-surface-100-900 border-surface-500/10 space-y-4 border p-5 shadow-md">
|
|
||||||
<div class="text-primary-500 flex items-center gap-2">
|
|
||||||
<Store size="1.2em" />
|
|
||||||
<h3
|
|
||||||
class="text-xs font-bold tracking-widest uppercase">
|
|
||||||
Exhibit Context
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-3">
|
|
||||||
{#if is_edit_mode}
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="text-sm opacity-60"
|
|
||||||
>Exhibit Name</span>
|
|
||||||
<span class="font-bold"
|
|
||||||
>{$lq__lead_obj.event_exhibit_name ||
|
|
||||||
'...'}</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="text-sm opacity-60"
|
|
||||||
>Captured By</span>
|
|
||||||
<span class="font-mono text-[10px]"
|
|
||||||
>{$lq__lead_obj.external_person_id ||
|
|
||||||
'Unknown'}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if is_edit_mode}
|
|
||||||
<div
|
|
||||||
class="border-surface-500/10 flex items-center justify-between border-t pt-2">
|
|
||||||
<span class="text-xs font-bold opacity-60"
|
|
||||||
>Priority Lead</span>
|
|
||||||
<Element_ae_obj_field_editor
|
|
||||||
object_type="event_exhibit_tracking"
|
|
||||||
object_id={exhibit_tracking_id ?? ''}
|
|
||||||
field_name="priority"
|
|
||||||
field_type="checkbox"
|
|
||||||
current_value={$lq__lead_obj.priority}
|
|
||||||
object_reload={true} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- System Info -->
|
|
||||||
<div
|
<div
|
||||||
class="card bg-surface-500/5 space-y-4 p-5 font-mono text-[10px] opacity-60 shadow-inner">
|
class="card bg-surface-500/5 space-y-4 p-5 font-mono text-[10px] opacity-60 shadow-inner">
|
||||||
<div
|
<div
|
||||||
@@ -477,12 +505,17 @@ function format_date(date: any) {
|
|||||||
<span class="opacity-50">PERSON ID:</span>
|
<span class="opacity-50">PERSON ID:</span>
|
||||||
{$lq__lead_obj.event_person_id}
|
{$lq__lead_obj.event_person_id}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="opacity-50">EXHIBIT:</span>
|
||||||
|
{$lq__lead_obj.event_exhibit_name || '—'}
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="opacity-50">MODIFIED:</span>
|
<span class="opacity-50">MODIFIED:</span>
|
||||||
{format_date($lq__lead_obj.updated_on)}
|
{format_date($lq__lead_obj.updated_on)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Restore Lead card — only shown when lead has been removed (enable=false/0).
|
<!-- Restore Lead card — only shown when lead has been removed (enable=false/0).
|
||||||
Removing sets enable=false rather than deleting so notes/responses are preserved. -->
|
Removing sets enable=false rather than deleting so notes/responses are preserved. -->
|
||||||
|
|||||||
@@ -19,21 +19,27 @@
|
|||||||
* Both are handled transparently.
|
* Both are handled transparently.
|
||||||
*/
|
*/
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
import { ae_api } from '$lib/stores/ae_stores';
|
import { ae_api } from '$lib/stores/ae_stores';
|
||||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||||
import { CircleCheck, LoaderCircle, Save } from '@lucide/svelte';
|
import { leads_loc } from '$lib/stores/ae_events_stores__leads.svelte';
|
||||||
|
import { ArrowRight, CircleCheck, LoaderCircle, Save, Settings } from '@lucide/svelte';
|
||||||
interface Props {
|
interface Props {
|
||||||
exhibit_tracking_id: string;
|
exhibit_tracking_id: string;
|
||||||
exhibit_id: string;
|
exhibit_id: string;
|
||||||
|
event_id: string; // For navigate-to-manage link
|
||||||
custom_questions_json?: string; // From event_exhibit
|
custom_questions_json?: string; // From event_exhibit
|
||||||
current_responses_json?: string; // From event_exhibit_tracking
|
current_responses_json?: string; // From event_exhibit_tracking
|
||||||
|
is_dirty?: boolean; // Bindable — parent reads this for unsaved-changes guard
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
exhibit_tracking_id,
|
exhibit_tracking_id,
|
||||||
exhibit_id,
|
exhibit_id,
|
||||||
|
event_id,
|
||||||
custom_questions_json = '[]',
|
custom_questions_json = '[]',
|
||||||
current_responses_json = '{}'
|
current_responses_json = '{}',
|
||||||
|
is_dirty = $bindable(false)
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let question_defs: any[] = $state([]);
|
let question_defs: any[] = $state([]);
|
||||||
@@ -42,6 +48,9 @@ let question_defs: any[] = $state([]);
|
|||||||
let flat_responses: Record<string, any> = $state({});
|
let flat_responses: Record<string, any> = $state({});
|
||||||
let status = $state('idle'); // idle, saving, success
|
let status = $state('idle'); // idle, saving, success
|
||||||
|
|
||||||
|
// Snapshot of responses as last saved (or as loaded). Used for dirty detection.
|
||||||
|
let saved_snapshot = $state('{}');
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
try {
|
try {
|
||||||
const defs =
|
const defs =
|
||||||
@@ -69,12 +78,18 @@ $effect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
flat_responses = flat;
|
flat_responses = flat;
|
||||||
|
saved_snapshot = JSON.stringify(flat);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to parse questions/responses', e);
|
console.error('Failed to parse questions/responses', e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Expose dirty state to parent so the unsaved-changes guard can check it.
|
||||||
|
$effect(() => {
|
||||||
|
is_dirty = JSON.stringify(flat_responses) !== saved_snapshot;
|
||||||
|
});
|
||||||
|
|
||||||
// Resolve the key for a question def (new: q.code, legacy: q.label)
|
// Resolve the key for a question def (new: q.code, legacy: q.label)
|
||||||
function q_key(q: any): string {
|
function q_key(q: any): string {
|
||||||
return q.code || q.label || '';
|
return q.code || q.label || '';
|
||||||
@@ -97,6 +112,7 @@ async function handle_save() {
|
|||||||
responses_json: JSON.stringify(nested)
|
responses_json: JSON.stringify(nested)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
saved_snapshot = JSON.stringify(flat_responses); // mark clean
|
||||||
status = 'success';
|
status = 'success';
|
||||||
setTimeout(() => (status = 'idle'), 2000);
|
setTimeout(() => (status = 'idle'), 2000);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -166,11 +182,26 @@ async function handle_save() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if question_defs.length === 0}
|
{#if question_defs.length === 0}
|
||||||
<p class="py-4 text-center italic opacity-30">
|
<!-- No questions set up yet — prompt them to configure rather than leaving a dead form. -->
|
||||||
No custom questions configured for this exhibit.
|
<div
|
||||||
|
class="preset-tonal-surface border-surface-500/20 flex flex-col items-center gap-3 rounded-xl border p-6 text-center">
|
||||||
|
<p class="text-sm font-semibold opacity-60">
|
||||||
|
No custom questions configured for this exhibit yet.
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-outlined-primary"
|
||||||
|
onclick={() => {
|
||||||
|
// Set the tab before navigating so the user lands directly in Manage.
|
||||||
|
leads_loc.current.tab[exhibit_id] = 'manage';
|
||||||
|
goto(`/events/${event_id}/leads/exhibit/${exhibit_id}`);
|
||||||
|
}}>
|
||||||
|
<Settings size="1.1em" class="mr-1" />
|
||||||
|
Configure in Manage Tab
|
||||||
|
<ArrowRight size="1.1em" class="ml-1" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
<button
|
<button
|
||||||
class="btn preset-filled-primary w-full font-bold shadow-lg"
|
class="btn preset-filled-primary w-full font-bold shadow-lg"
|
||||||
disabled={status === 'saving'}
|
disabled={status === 'saving'}
|
||||||
@@ -183,4 +214,5 @@ async function handle_save() {
|
|||||||
<Save size="1.2em" class="mr-2" /> Save Responses
|
<Save size="1.2em" class="mr-2" /> Save Responses
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user