fix: thread logged_at through message stack; Esc handler and localNow fixes

- scripts/messaging.py: add logged_at param to create_message; use provided value or fall back to _now_utc()
- dev-api.py: add logged_at: Optional[str] = None to MessageCreateBody
- web/src/stores/messaging.ts: remove logged_at from Omit, add as optional intersection so callers can pass it through
- web/src/components/MessageLogModal.vue: pass logged_at in handleSubmit payload; move @keydown.esc from backdrop to modal-dialog (which holds focus); compute localNow fresh inside watch so it reflects actual open time
This commit is contained in:
pyr0ball 2026-04-20 12:55:41 -07:00
parent 8df3297ab6
commit b77ec81cc6
4 changed files with 14 additions and 12 deletions

View file

@ -4192,6 +4192,7 @@ class MessageCreateBody(BaseModel):
from_addr: Optional[str] = None
to_addr: Optional[str] = None
template_id: Optional[int] = None
logged_at: Optional[str] = None
class TemplateCreateBody(BaseModel):

View file

@ -47,6 +47,7 @@ def create_message(
from_addr: Optional[str],
to_addr: Optional[str],
template_id: Optional[int],
logged_at: Optional[str] = None,
) -> dict:
"""Insert a new message row and return it as a dict."""
con = _connect(db_path)
@ -55,12 +56,12 @@ def create_message(
"""
INSERT INTO messages
(job_id, job_contact_id, type, direction, subject, body,
from_addr, to_addr, template_id)
from_addr, to_addr, logged_at, template_id)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(job_id, job_contact_id, type, direction, subject, body,
from_addr, to_addr, template_id),
from_addr, to_addr, logged_at or _now_utc(), template_id),
)
con.commit()
row = con.execute(

View file

@ -5,7 +5,6 @@
v-if="show"
class="modal-backdrop"
@click.self="emit('close')"
@keydown.esc="emit('close')"
>
<div
ref="dialogEl"
@ -14,6 +13,7 @@
aria-modal="true"
:aria-label="title"
tabindex="-1"
@keydown.esc="emit('close')"
>
<header class="modal-header">
<h2 class="modal-title">{{ title }}</h2>
@ -93,21 +93,20 @@ const title = computed(() =>
props.type === 'call_note' ? 'Log a call' : 'Log an in-person note'
)
const now = new Date()
const localNow = new Date(now.getTime() - now.getTimezoneOffset() * 60000)
.toISOString()
.slice(0, 16)
const form = ref({
direction: '',
subject: '',
body: '',
logged_at: localNow,
logged_at: '',
})
// Focus the dialog when it opens
// Focus the dialog when it opens; compute localNow fresh each time
watch(() => props.show, async (val) => {
if (val) {
const now = new Date()
const localNow = new Date(now.getTime() - now.getTimezoneOffset() * 60000)
.toISOString()
.slice(0, 16)
error.value = null
form.value = { direction: '', subject: '', body: '', logged_at: localNow }
await nextTick()
@ -129,6 +128,7 @@ async function handleSubmit() {
from_addr: null,
to_addr: null,
template_id: null,
logged_at: form.value.logged_at || undefined,
})
saving.value = false
if (result) emit('saved')

View file

@ -60,7 +60,7 @@ export const useMessagingStore = defineStore('messaging', () => {
templates.value = data ?? []
}
async function createMessage(payload: Omit<Message, 'id' | 'logged_at' | 'approved_at' | 'osprey_call_id'>) {
async function createMessage(payload: Omit<Message, 'id' | 'approved_at' | 'osprey_call_id'> & { logged_at?: string }) {
saving.value = true
error.value = null
const { data, error: fetchErr } = await useApiFetch<Message>(