• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Freegle / iznik-nuxt3 / f1b2e232-33ec-457b-9de8-c38d9a34f62e

28 Nov 2025 11:02PM UTC coverage: 44.781% (+1.2%) from 43.578%
f1b2e232-33ec-457b-9de8-c38d9a34f62e

push

circleci

actions-user
Auto-merge production to app-ci-fd (daily scheduled)

Automated merge from production branch after successful tests.

🤖 Automated by GitHub Actions

3197 of 7643 branches covered (41.83%)

Branch coverage included in aggregate %.

9 of 9 new or added lines in 1 file covered. (100.0%)

112 existing lines in 11 files now uncovered.

3470 of 7245 relevant lines covered (47.9%)

12.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/components/ChatMessagePromised.vue
1
<template>
2
  <div class="clearfix">
×
3
    <div v-if="chatmessage?.userid != myid" class="media">
4
      <div v-if="!refmsg">
5
        This chat message refers to a post (<v-icon
6
          icon="hashtag"
7
          class="text-muted fa-0-8x"
8
        />{{ chatmessage.refmsgid }}) which has been deleted.
9
      </div>
10
      <b-card v-else border-variant="success" class="ml-2">
11
        <b-card-title>
12
          <nuxt-link
13
            no-prefetch
14
            :to="
15
              (messageIsFromCurrentUser ? '/mypost/' : '/message/') + refmsgid
16
            "
17
          >
18
            <b-img
19
              v-if="refmsg?.attachments?.length > 0"
20
              class="float-end ml-1"
21
              rounded
22
              thumbnail
23
              generator-unable-to-provide-required-alt=""
24
              lazy
25
              :src="refmsg.attachments[0].paththumb"
26
              width="70px"
27
              @error="brokenImage"
28
            />
29
          </nuxt-link>
×
30
          <ProfileImage
31
            :image="otheruser.profile.paththumb"
32
            class="mr-1 mb-1 mt-1 inline"
33
            is-thumbnail
34
            size="sm"
35
          />
36
          <span class="small black">Good news! You've been promised this:</span>
×
37
          <br />
38
          <nuxt-link
39
            no-prefetch
40
            :to="
41
              (messageIsFromCurrentUser ? '/mypost/' : '/message/') + refmsgid
42
            "
43
          >
44
            <h4>
45
              {{ refmsg?.subject }}
46
            </h4>
×
47
          </nuxt-link>
48
          <AddToCalendar
49
            v-if="tryst?.calendarLink"
50
            :calendar-link="tryst.calendarLink"
51
            class="mr-2"
52
          />
×
53
          <notice-message
54
            v-if="refmsg.outcomes?.length || refmsg.deleted"
55
            class="mt-2 mb-2"
56
          >
57
            <v-icon icon="info-circle" />
58
            <span v-if="refmsg.type === 'Offer'">
×
59
              This is no longer available.
60
            </span>
61
            <span v-else> They are no longer looking for this. </span>
62
          </notice-message>
63
        </b-card-title>
64
        <b-card-text>
65
          <div :class="emessage ? 'media-body chatMessage' : 'media-body'">
×
66
            <span>
67
              <span
68
                v-if="
×
69
                  chatmessage.secondsago < 60 ||
70
                  chatmessage.id > chat.lastmsgseen
71
                "
72
                class="prewrap font-weight-bold"
73
                >{{ emessage }}</span
74
              >
75
              <span v-else class="preline forcebreak">{{ emessage }}</span>
76
              <b-img
77
                v-if="chatmessage.image"
×
78
                fluid
79
                :src="chatmessage.image.path"
80
                lazy
81
                rounded
82
              />
83
            </span>
84
          </div>
85
        </b-card-text>
86
      </b-card>
87
    </div>
88
    <div v-else class="media float-end">
89
      <div v-if="!refmsg">
90
        This chat message refers to a post (<v-icon
91
          icon="hashtag"
92
          class="text-muted fa-0-8x"
93
        />{{ chatmessage.refmsgid }}) which has been deleted.
94
      </div>
95
      <b-card v-else border-variant="success">
96
        <b-card-title>
97
          <nuxt-link
98
            no-prefetch
99
            :to="
100
              (messageIsFromCurrentUser ? '/mypost/' : '/message/') + refmsgid
101
            "
102
          >
103
            <b-img
104
              v-if="refmsg && refmsg.attachments?.length > 0"
×
105
              class="float-end"
106
              rounded
107
              thumbnail
108
              generator-unable-to-provide-required-alt=""
109
              lazy
110
              :src="refmsg.attachments[0].paththumb"
111
              width="70px"
112
              @error="brokenImage"
113
            />
UNCOV
114
          </nuxt-link>
×
115
          <div class="d-flex justify-content-start align-items-center">
116
            <ProfileImage
117
              :image="me.profile.path"
118
              class="mr-1 inline"
119
              is-thumbnail
120
              size="sm"
121
            />
122
            <div class="small black">
123
              You promised <strong>{{ otheruser.displayname }}</strong
×
124
              >:
125
            </div>
126
          </div>
127
          <nuxt-link
128
            no-prefetch
129
            :to="
130
              (messageIsFromCurrentUser ? '/mypost/' : '/message/') + refmsgid
131
            "
132
            class="nodecor"
133
          >
134
            <h4>
135
              {{ refmsg?.subject }}
136
            </h4>
137
          </nuxt-link>
138
          <p v-if="tryst?.arrangedfor" class="small text-info">
139
            Handover arranged for
140
            <strong
141
              ><DateFormatted :value="tryst.arrangedfor" format="weekdaytime"
142
            /></strong>
143
          </p>
144
          <div
145
            v-if="refmsg"
146
            class="d-flex mt-1 flex-wrap justify-content-between"
147
          >
148
            <template v-if="tryst">
×
149
              <AddToCalendar
150
                v-if="tryst?.calendarLink"
151
                :calendar-link="tryst.calendarLink"
152
                class="mr-2 mb-1"
153
              />
154
              <b-button
155
                v-if="refmsg.promisecount && refmsg.availablenow"
×
156
                variant="secondary"
157
                class="mr-2 mb-1"
158
                @click="changeTime"
159
              >
160
                <v-icon icon="pen" />
×
161
                Change time
162
              </b-button>
163
            </template>
164
            <template v-else-if="refmsg.promisecount && refmsg.availablenow">
165
              <b-button
166
                variant="secondary"
167
                class="mr-2 mb-1"
168
                @click="changeTime"
169
              >
170
                <v-icon icon="pen" />
×
171
                Set time
172
              </b-button>
173
            </template>
174
            <b-button
175
              v-if="refmsg.promisecount && refmsg.availablenow"
×
176
              variant="warning"
177
              class="align-middle mr-2 mb-1"
178
              @click="unpromise"
179
            >
180
              Unpromise
181
            </b-button>
×
182
            <b-button
183
              v-if="refmsg.availablenow"
184
              variant="primary"
185
              class="mr-1 mb-1"
186
              @click="outcome('Taken')"
×
187
            >
188
              Mark as TAKEN
189
            </b-button>
×
190
          </div>
191
          <PromiseModal
192
            v-if="showPromise"
×
193
            :messages="[refmsg]"
194
            :selected-message="refmsgid"
195
            :users="otheruser ? [otheruser] : []"
×
196
            :selected-user="otheruser ? otheruser.id : null"
×
197
            @hidden="showPromise = false"
×
198
          />
199
        </b-card-title>
200
        <b-card-text>
201
          <div :class="emessage ? 'media-body chatMessage' : 'media-body'">
×
202
            <span>
203
              <span
204
                v-if="
×
205
                  chatmessage.secondsago < 60 ||
206
                  chatmessage.id > chat.lastmsgseen
207
                "
208
                class="prewrap font-weight-bold"
209
                >{{ emessage }}</span
210
              >
211
              <span v-else class="preline forcebreak">{{ emessage }}</span>
212
              <b-img
213
                v-if="chatmessage.image"
×
214
                fluid
215
                :src="chatmessage.image.path"
216
                lazy
217
                rounded
218
              />
219
            </span>
UNCOV
220
          </div>
×
221
          <p v-if="!refmsg?.availablenow" class="text-muted">
×
222
            This has now been taken.
223
          </p>
224
        </b-card-text>
225
      </b-card>
226
    </div>
227
    <RenegeModal
228
      v-if="showRenege && refmsgid"
×
229
      :messages="[refmsgid]"
230
      :selected-message="refmsgid"
231
      :users="[otheruser]"
232
      :selected-user="otheruser.id"
233
      @hide="fetchMessages"
234
      @hidden="showRenege = false"
×
235
    />
236
    <OutcomeModal
237
      v-if="showOutcome && refmsgid"
×
238
      :id="refmsgid"
239
      :taken-by="takenBy"
240
      :type="outcomeType"
241
      @outcome="fetchMessage"
242
      @hidden="showOutcome = false"
×
243
    />
244
  </div>
245
</template>
246
<script setup>
247
import { ref, defineAsyncComponent } from 'vue'
248
import DateFormatted from './DateFormatted'
249
import { useTrystStore } from '~/stores/tryst'
250
import { fetchOurOffers } from '~/composables/useThrottle'
251
import { useChatStore } from '~/stores/chat'
252
import {
253
  fetchReferencedMessage,
254
  useChatMessageBase,
255
} from '~/composables/useChat'
256
import { useMessageStore } from '~/stores/message'
257
import AddToCalendar from '~/components/AddToCalendar'
258
import ProfileImage from '~/components/ProfileImage'
259

UNCOV
260
const OutcomeModal = defineAsyncComponent(() =>
×
261
  import('~/components/OutcomeModal')
262
)
263

UNCOV
264
const RenegeModal = defineAsyncComponent(() => import('./RenegeModal'))
×
UNCOV
265
const PromiseModal = defineAsyncComponent(() =>
×
266
  import('~/components/PromiseModal')
267
)
268

UNCOV
269
const props = defineProps({
×
270
  chatid: {
271
    type: Number,
272
    required: true,
273
  },
274
  id: {
275
    type: Number,
276
    required: true,
277
  },
278
  last: {
279
    type: Boolean,
280
    required: false,
281
    default: false,
282
  },
283
  pov: {
284
    type: Number,
285
    required: false,
286
    default: null,
287
  },
288
  highlightEmails: {
289
    type: Boolean,
290
    required: false,
291
    default: false,
292
  },
293
})
294

295
// Data properties
296
const showRenege = ref(false)
×
297
const showOutcome = ref(false)
×
298
const outcomeType = ref(null)
×
UNCOV
299
const showPromise = ref(false)
×
300

301
// Stores
302
const trystStore = useTrystStore()
×
UNCOV
303
const chatStore = useChatStore()
×
UNCOV
304
const messageStore = useMessageStore()
×
305

306
// Setup
UNCOV
307
await trystStore.fetch()
×
UNCOV
308
await fetchReferencedMessage(props.chatid, props.id)
×
309

310
// Use the chat base composable
UNCOV
311
const {
×
312
  chat,
313
  chatmessage,
314
  emessage,
315
  messageIsFromCurrentUser,
316
  refmsgid,
317
  refmsg,
318
  me,
319
  myid,
320
  otheruser,
321
  brokenImage,
322
  fetchMessage,
323
} = useChatMessageBase(props.chatid, props.id, props.pov)
324

325
if (refmsgid.value) {
×
UNCOV
326
  useMessageStore().fetch(refmsgid.value)
×
327
}
328

329
// Component-specific computed properties
UNCOV
330
const tryst = computed(() => {
×
331
  return otheruser.value ? trystStore?.getByUser(otheruser.value.id) : null
×
332
})
333

334
const takenBy = computed(() => {
×
UNCOV
335
  let ret = null
×
336

337
  if (otheruser.value) {
×
UNCOV
338
    ret = otheruser.value
×
UNCOV
339
    ret.userid = otheruser.value.id
×
UNCOV
340
    ret.count = 1
×
341
  }
342

343
  return ret
×
344
})
345

346
// Methods
347
function unpromise() {
×
UNCOV
348
  showRenege.value = true
×
UNCOV
349
  fetchOurOffers()
×
350
}
351

UNCOV
352
function changeTime() {
×
UNCOV
353
  showPromise.value = true
×
354
}
355

UNCOV
356
function fetchMessages() {
×
357
  chatStore.fetchMessages(chatmessage.value.chatid)
×
358
}
359

UNCOV
360
async function outcome(type) {
×
UNCOV
361
  await messageStore.fetch(refmsgid.value)
×
362

UNCOV
363
  showOutcome.value = true
×
UNCOV
364
  outcomeType.value = type
×
365
}
366
</script>
367
<style scoped lang="scss">
368
.chatMessage {
369
  border: 1px solid $color-gray--light;
370
  border-radius: 10px;
371
  padding-top: 2px;
372
  padding-bottom: 2px;
373
  padding-left: 4px;
374
  padding-right: 2px;
375
  word-wrap: break-word;
376
  line-height: 1.5;
377
}
378
</style>
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc