(props: StateHeaderProps)
| 14 | } |
| 15 | |
| 16 | export function StateHeader(props: StateHeaderProps) { |
| 17 | const styles = useStyles() |
| 18 | |
| 19 | const [now, setNow] = createSignal(dayjs().unix()) |
| 20 | |
| 21 | onMount(() => { |
| 22 | const interval = setInterval(() => setNow(dayjs().unix()), 1000) |
| 23 | onCleanup(() => clearInterval(interval)) |
| 24 | }) |
| 25 | |
| 26 | const state = props.selectedInstance |
| 27 | |
| 28 | const updatedAt = createMemo(() => state()?.date.unix() ?? dayjs().unix()) |
| 29 | |
| 30 | const relativeTimeText = createMemo(() => { |
| 31 | // Math.max to account for signal update |
| 32 | const diffSeconds = Math.max(now() - updatedAt(), 0) |
| 33 | if (diffSeconds < 60) { |
| 34 | return `${diffSeconds} second${diffSeconds !== 1 ? 's' : ''} ago` |
| 35 | } |
| 36 | return dayjs.unix(updatedAt()).fromNow() |
| 37 | }) |
| 38 | |
| 39 | if (!state()) return null |
| 40 | |
| 41 | return ( |
| 42 | <div class={styles().stateHeader}> |
| 43 | <div class={styles().stateTitle}>Form state</div> |
| 44 | <div style={{ display: 'flex', 'align-items': 'center', gap: '16px' }}> |
| 45 | <div class={styles().infoGrid}> |
| 46 | <div class={styles().infoLabel}>Key</div> |
| 47 | <div class={styles().infoValueMono}>{state()!.id}</div> |
| 48 | <div class={styles().infoLabel}>Last Updated</div> |
| 49 | <div class={styles().infoValueMono}> |
| 50 | {new Date(updatedAt() * 1000).toLocaleTimeString()} ( |
| 51 | {relativeTimeText()}) |
| 52 | </div> |
| 53 | </div> |
| 54 | </div> |
| 55 | </div> |
| 56 | ) |
| 57 | } |
nothing calls this directly
no test coverage detected