<div class="messenger"></div>
<div class="messenger"></div>
/* No context defined. */
  • Content:
    <?php
    
    namespace Theme\Views\Molecules\messenger;
    
    use ACFToolkit\Types\CustomMolecule;
    
    
    class Messenger extends CustomMolecule
    {
        public string $name = 'messenger';
        public string $label = 'Messenger';
        public int $needsJs = 0;
        public int $needsVue = 1;
        public int $needsVueInitialisation = 1;
    
        public function __construct($name = '', $title = '', $children = [])
        {
            parent::__construct($name, $title);
            $this->addChildren(array_merge($children, [
            ]));
        }
    }
  • URL: /components/raw/messenger/Messenger.php
  • Filesystem Path: resources/Views/Molecules/messenger/Messenger.php
  • Size: 509 Bytes
  • Content:
    <?php
    
    namespace Theme\Views\Molecules\messenger;
    
    use ACFToolkit\ViewModels\BaseViewModel;
    
    class MessengerViewModel extends BaseViewModel
    {
    }
    
  • URL: /components/raw/messenger/MessengerViewModel.php
  • Filesystem Path: resources/Views/Molecules/messenger/MessengerViewModel.php
  • Size: 144 Bytes
  • Content:
    <template>
      <div :class="{'mb-1 flex-basis-1/2': true, 'self-start': from_id !== id, 'self-end': from_id === id}">
        <strong v-text="from"></strong>
        <p v-text="body"></p>
        <small v-text="date"></small>
      </div>
    </template>
    <script>
    /* IMPORTS */
    import {mapGetters} from 'vuex';
    
    export default {
      components: {},
      props: {
        body: {
          type: String
        },
        from: {
          type: String
        },
        date: {
          type: String
        },
        isNew: {
          type: Boolean
        },
        from_id: {
          type: String
        }
      },
      data: () => {
        return {}
      },
      computed: {
        ...mapGetters('Member', ['id']),
        getThreads() {
    
        },
        getClass(){
          return this.id === this.from_id
        }
      },
      methods: {
      },
      async created() {
    
      }
    }
    </script>
    
  • URL: /components/raw/messenger/message.vue
  • Filesystem Path: resources/Views/Molecules/messenger/message.vue
  • Size: 768 Bytes
  • Content:
    <template>
      <div class="flex flex-col rounded-md border border-lighter px-1 h-full" v-if="!loading && id">
        <div class="header flex justify-between items-center py-1.5 h-1/10">
          <icon
            type="iconoir"
            icon="nav-arrow-left"
            class-name="cursor-pointer"
            @click="goBack"
          />
          <button
            @click="createNewMessage"
            class="flex justify-between items-center gap-x-1"
          >
            <Headline
              :headline="$t('Neue Nachricht')"
              type="h3"
              class-name="cursor-pointer"
            />
            <icon
              type="iconoir"
              icon="edit-pencil"
            />
          </button>
        </div>
        <div class="flex flex-row relative h-9/10 gap-x-2">
          <div class="threads w-full h-full sm:w-auto sm:basis-1/3">
            <Thread
              :active="currentThread && currentThread.id === thread.id"
              v-for="thread in threads"
              :subject="thread.subject"
              :preview="thread.preview"
              :id="thread.id"
              :creator="thread.creator"
              :participants="thread.participants"
              :unread-messages="thread.unreadMessagesCount"
              :is-new="thread.isNew"
              @click="selectThread(thread)"
            />
          </div>
          <div :class="{
            'absolute justify-between h-full w-full sm:w-auto bg-white sm:relative right-0 sm:right-auto sm:translate-x-0 flex flex-col sm:basis-2/3': 1,
            'translate-x-full': !currentThread,
            'translate-x-0': currentThread
          }">
            <div class="flex flex-col h-7/10">
              <Headline
                v-if="currentThread"
                :headline="getFromLine(currentThread)"
                type="h3"
                class-name="sm:hidden text-center mb-1"
              />
              <div class="messages flex flex-col h-full overflow-scroll">
                <label v-if="(currentThread && currentThread.isNew)" v-text="$t('Empfänger')"></label>
                <AutoComplete
                  v-model="query"
                  :suggestions="recipientItems"
                  @complete="getRecipients"
                  multiple
                  @item-select="addRecipient"
                  option-label="name"
                  data-key="id"
                  class="w-full mb-1"
                  v-if="currentThread && currentThread.isNew"
                />
                <Message
                  v-for="message in currentMessages"
                  :body="message.body"
                  :from="message.from"
                  :date="message.date"
                  :from_id="message.from_id"
                />
              </div>
            </div>
            <div class="flex flex-col gap-y-0.5">
              <div>
                <label v-if="(currentThread && currentThread.isNew)" v-text="$t('Nachricht')"></label>
                <textarea
                  v-model="newMessage"
                  rows="4"
                  v-if="currentMessages && currentMessages.length || (currentThread && currentThread.isNew)"
                  class="mb-1"
                ></textarea>
              </div>
              <CustomButton
                v-if="newMessage && newMessage.trim() !== ''"
                :cta="$t('Nachricht absenden')"
                @click="sendMessage"
                type="x-btn--accent"
              />
            </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    /* IMPORTS */
    import Thread from './thread.vue';
    import Message from './message.vue';
    import CustomButton from '../../Atoms/button/button.vue';
    import AutoComplete from 'primevue/autocomplete';
    import MemberService from '../../Assets/src/js/services/MemberService';
    import MessageService from '../../Assets/src/js/services/MessageService';
    import Headline from '../../Atoms/headline/headline.vue';
    import Icon from '../../Atoms/icon/icon.vue';
    import {mapGetters} from 'vuex';
    
    export default {
      components: {
        Icon,
        Headline,
        CustomButton,
        Thread,
        Message,
        AutoComplete
      },
      props: {
        initialThreads: {
          type: Array,
        },
      },
      data: () => {
        return {
          query: '',
          recipients: [],
          recipientItems: [],
          currentThread: null,
          threads: [],
          messages: {},
          currentMessages: [],
          newMessage: ''
        }
      },
      computed: {
        ...mapGetters('Member', ['id', 'name', 'loading']),
        getThreads() {
    
        },
        getFirstThread() {
          return this.initialThreads.threads[0] || null
        },
      },
      methods: {
        goBack() {
          window.history.back()
        },
        getFromLine(thread) {
          return [thread.creator, thread.participants]
            .filter(item => item && (item.trim() !== ''))
            .join(', ')
        },
        async getRecipients($e) {
          const {data} = await MemberService.getMembers({query: $e.query})
          this.recipientItems = data
        },
        async addRecipient(e) {
          this.recipients.push(e.value.id)
        },
        async sendMessage() {
          const {data} = this.currentThread.isNew ?
            await MessageService.createThread({
              message: this.newMessage,
              recipients: this.recipients
            }) :
            await MessageService.updateThread({
              threadId: this.currentThread.id,
              message: this.newMessage,
            })
          this.currentMessages.push(data.data)
        },
        createNewMessage() {
          const thread = {
            subject: this.$t('Neue Nachricht'),
            isNew: true,
            messages: []
          }
          this.newMessage = ''
          this.threads.unshift(thread)
          this.currentThread = thread
          this.currentMessages = this.currentThread.messages
        },
        getInitialMessages() {
          const initialThread = this.getFirstThread
          this.currentThread = initialThread
          this.currentMessages = initialThread ? initialThread.messages : []
        },
        selectThread(thread) {
          this.newMessage = ''
          this.currentThread = thread
          this.currentMessages = thread.messages
        }
      },
      async created() {
        this.threads = this.initialThreads.threads
        if (innerWidth > 768)
          this.getInitialMessages()
      }
    }
    </script>
    <style lang="scss">
    .messenger-container {
      height: 80dvh;
    }
    
    .p-autocomplete {
      ul {
        @apply w-full gap-0.5 border border-grey rounded-md px-1 py-0.5 text-primary placeholder-primary/90 bg-lighter outline-accent;
      }
    
      .p-autocomplete-token {
        @apply bg-white gap-x-0.5 px-0.5 py-0.25 rounded-md;
      }
    
      input {
      }
    }
    </style>
    
  • URL: /components/raw/messenger/messenger.vue
  • Filesystem Path: resources/Views/Molecules/messenger/messenger.vue
  • Size: 6.2 KB
  • Content:
    <template>
      <div :class="{'thread mb-0.5 p-0.5 rounded-md': 1, 'bg-accent': active}">
        <strong v-if="isNew" v-text="subject"></strong>
        <strong
          v-if="unreadMessagesCount > 0"
          v-text="fromLine"
        ></strong>
        <p
          class="from"
          v-else
          v-text="fromLine"
          :title="fromLine"
        ></p>
        <p v-text="preview"></p>
      </div>
    </template>
    <script>
    /* IMPORTS */
    
    export default {
      components: {},
      props: {
        active: {
          type: Boolean
        },
        subject: {
          type: String,
        },
        preview: {
          type: String,
        },
        id: {
          type: Number,
        },
        unreadMessagesCount: {
          type: Number,
        },
        creator: {
          type: String,
        },
        participants: {
          type: String,
        },
        isNew: {
          type: Boolean,
        }
      },
      data: () => {
        return {
        }
      },
      computed: {
        fromLine(){
          return [this.creator, this.participants]
            .filter(item => item && (item.trim() !== ''))
            .join(', ')
        }
      },
      methods: {
      },
      async created(){
    
      }
    }
    </script>
    <style lang="scss">
      .thread {
        @apply cursor-pointer;
      }
      .from {
        @apply overflow-ellipsis text-ellipsis;
      }
    </style>
    
  • URL: /components/raw/messenger/thread.vue
  • Filesystem Path: resources/Views/Molecules/messenger/thread.vue
  • Size: 1.2 KB

Messenger

{% include '@molecules/messenger/messenger.twig' with {

    } only %}

ACF

Fields