From ac05a5ed2b403efacec9e9ad5e9462887730cc0b Mon Sep 17 00:00:00 2001 From: felix Date: Sat, 26 Sep 2026 18:22:27 +0200 Subject: [PATCH] clean up frontend --- app/components/chat/new-conversation.hbs | 9 ++ .../chat/new-conversation.js} | 4 +- app/components/chat/sidebar.hbs | 29 +++++++ app/components/chat/window.hbs | 5 +- app/helpers/format-datetime.js | 16 ++++ app/modifiers/chat-scroll-bottom.js | 17 ++++ app/routes/conversation.js | 8 +- app/styles/app.scss | 87 +++++++++++++++++++ app/templates/conversation.hbs | 19 +++- app/templates/conversations.hbs | 33 +++---- 10 files changed, 199 insertions(+), 28 deletions(-) create mode 100644 app/components/chat/new-conversation.hbs rename app/{controllers/conversations.js => components/chat/new-conversation.js} (81%) create mode 100644 app/components/chat/sidebar.hbs create mode 100644 app/helpers/format-datetime.js create mode 100644 app/modifiers/chat-scroll-bottom.js diff --git a/app/components/chat/new-conversation.hbs b/app/components/chat/new-conversation.hbs new file mode 100644 index 0000000..042f505 --- /dev/null +++ b/app/components/chat/new-conversation.hbs @@ -0,0 +1,9 @@ + + Nieuw gesprek + \ No newline at end of file diff --git a/app/controllers/conversations.js b/app/components/chat/new-conversation.js similarity index 81% rename from app/controllers/conversations.js rename to app/components/chat/new-conversation.js index 0bcab31..b4939f0 100644 --- a/app/controllers/conversations.js +++ b/app/components/chat/new-conversation.js @@ -1,8 +1,8 @@ -import Controller from '@ember/controller'; +import Component from '@glimmer/component'; import { service } from '@ember/service'; import { task } from 'ember-concurrency'; -export default class ConversationsController extends Controller { +export default class ChatNewConversation extends Component { @service store; @service router; @service currentSession; diff --git a/app/components/chat/sidebar.hbs b/app/components/chat/sidebar.hbs new file mode 100644 index 0000000..64c0c55 --- /dev/null +++ b/app/components/chat/sidebar.hbs @@ -0,0 +1,29 @@ +
+
+ Gesprekken +
+
+
    + {{#each @conversations as |conversation|}} +
  • + + + {{if conversation.title conversation.title "Nieuw gesprek"}} + + + {{format-datetime conversation.lastActivity}} + + +
  • + {{else}} +
  • +

    Nog geen gesprekken.

    +
  • + {{/each}} +
+
+
\ No newline at end of file diff --git a/app/components/chat/window.hbs b/app/components/chat/window.hbs index 7502c06..764ea45 100644 --- a/app/components/chat/window.hbs +++ b/app/components/chat/window.hbs @@ -1,6 +1,9 @@ {{! The list, the composer, the poll loop }}
-
+
{{#unless this.messages.length}}

{{@assistant.description}}

{{/unless}} diff --git a/app/helpers/format-datetime.js b/app/helpers/format-datetime.js new file mode 100644 index 0000000..f749483 --- /dev/null +++ b/app/helpers/format-datetime.js @@ -0,0 +1,16 @@ +import { helper } from '@ember/component/helper'; + +const DATE = new Intl.DateTimeFormat('nl-BE', { + day: '2-digit', + month: '2-digit', + year: 'numeric', +}); +const TIME = new Intl.DateTimeFormat('nl-BE', { + hour: '2-digit', + minute: '2-digit', +}); + +export default helper(([date]) => { + if (!date) return ''; + return `${DATE.format(date)} ${TIME.format(date)}`; +}); diff --git a/app/modifiers/chat-scroll-bottom.js b/app/modifiers/chat-scroll-bottom.js new file mode 100644 index 0000000..06b48a3 --- /dev/null +++ b/app/modifiers/chat-scroll-bottom.js @@ -0,0 +1,17 @@ +import Modifier from 'ember-modifier'; + +// Keeps the chat scrolled to the bottom: on insert, when another +// conversation is opened, and when the number of messages changes. The same +// conversation and count (e.g. a poll reload) leaves the scroll position +// alone, so reading history is not interrupted. +export default class ChatScrollBottom extends Modifier { + lastKey = null; + + modify(element, positional) { + const [id, count] = positional; + const key = `${id}:${count}`; + if (key === this.lastKey) return; + this.lastKey = key; + element.scrollTop = element.scrollHeight; + } +} diff --git a/app/routes/conversation.js b/app/routes/conversation.js index c087d55..a6a41f9 100644 --- a/app/routes/conversation.js +++ b/app/routes/conversation.js @@ -10,13 +10,17 @@ export default class ConversationRoute extends Route { } async model({ id }) { - const [conversation, agents] = await Promise.all([ + const [conversation, agents, conversations] = await Promise.all([ this.store.findRecord('chat-conversation', id, { include: 'messages.attachments', reload: true, }), this.store.query('chat-agent', { 'page[size]': 1 }), + this.store.query('chat-conversation', { + sort: '-last-activity', + 'page[size]': 50, + }), ]); - return { conversation, assistant: agents[0] }; + return { conversation, assistant: agents[0], conversations }; } } diff --git a/app/styles/app.scss b/app/styles/app.scss index dbf3dbe..03821cd 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -27,10 +27,97 @@ @import "@appuniversum/ember-appuniversum/styles/a-utilities"; // CHAT + +/* ================================== + #CHAT LAYOUT + Sidebar with the conversation overview (1/5 of the screen) next to a + content area that fills the rest of the screen under the main header. + ================================== */ +.chat-sidebar { + @include mq(medium) { + flex-basis: 20%; + flex-grow: 0; + flex-shrink: 0; + } +} +/* The conversations are listed as navigation: title on top, date + time in + subscript. Titles are truncated when they do not fit. */ +.chat-sidebar__list { + display: block; +} +.chat-sidebar__link { + flex-direction: column; + align-items: flex-start; + gap: 0.1rem; +} +.chat-sidebar__title { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.chat-sidebar__meta { + font-size: var(--au-tiny); + color: var(--au-gray-600); + text-decoration: none; +} +.chat-sidebar__empty { + margin: 0; + padding: $au-unit-tiny * 1.5 $au-unit-small; + + @include mq(medium) { + padding: $au-unit-small $au-unit-small + $au-unit-tiny; + } +} + +.chat-content { + display: flex; + flex-direction: column; + min-width: 0; +} + +/* Bar above the chat: the conversation title, truncated, and a button to + start a new conversation. */ +.chat-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.6rem 1rem; + border-bottom: 1px solid var(--au-gray-200); + flex-shrink: 0; +} +.chat-toolbar__title { + margin: 0; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* The conversations overview: a big button to start a conversation. */ +.chat-start { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + min-height: calc(100vh - 8rem); + + @include mq(medium) { + min-height: 0; + } +} + .chat-window { display: flex; flex-direction: column; + flex: 1; + min-height: 0; height: calc(100vh - 8rem); + + @include mq(medium) { + height: auto; + } } .chat-window__messages { flex: 1; diff --git a/app/templates/conversation.hbs b/app/templates/conversation.hbs index 5cf0061..13036ff 100644 --- a/app/templates/conversation.hbs +++ b/app/templates/conversation.hbs @@ -1,6 +1,21 @@ - +
+ +
+ +
+
+ + {{if @model.conversation.title @model.conversation.title "Nieuw gesprek"}} + + +
+ - \ No newline at end of file +
\ No newline at end of file diff --git a/app/templates/conversations.hbs b/app/templates/conversations.hbs index a48b1fc..a632fd3 100644 --- a/app/templates/conversations.hbs +++ b/app/templates/conversations.hbs @@ -1,22 +1,13 @@ - -
- Gesprekken - - Nieuw gesprek - - - {{#each @model as |conversation|}} - - - {{if conversation.title conversation.title "Nieuw gesprek"}} - - - {{else}} -

Nog geen gesprekken.

- {{/each}} -
+
+ +
+ +
+
+
- \ No newline at end of file +
\ No newline at end of file