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

Freegle / iznik-nuxt3 / 38f66207-6066-47b4-bc2e-4c69e60182e5

03 Dec 2025 11:02PM UTC coverage: 42.1% (-6.5%) from 48.587%
38f66207-6066-47b4-bc2e-4c69e60182e5

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

2800 of 7561 branches covered (37.03%)

Branch coverage included in aggregate %.

248 of 640 new or added lines in 45 files covered. (38.75%)

582 existing lines in 34 files now uncovered.

3448 of 7280 relevant lines covered (47.36%)

22.66 hits per line

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

0.0
/components/ChatMessagePromised.vue
1
<template>
NEW
2
  <div class="chat-message-promised">
×
3
    <!-- Received promise (from other user) -->
4
    <div v-if="chatmessage?.userid != myid" class="promised-message">
5
      <div v-if="!refmsg" class="text-muted small">
6
        This chat message refers to a post (<v-icon
7
          icon="hashtag"
8
          class="text-muted fa-0-8x"
9
        />{{ chatmessage.refmsgid }}) which has been deleted.
10
      </div>
11
      <div v-else class="promised-wrapper">
12
        <div class="promised-header">
13
          <ProfileImage
14
            :image="otheruser.profile.paththumb"
15
            :name="otheruser.displayname"
16
            class="mr-2 inline"
17
            is-thumbnail
18
            size="sm"
19
          />
20
          <span class="promised-label"
×
21
            >Good news! You've been promised this:</span
22
          >
23
        </div>
24
        <ChatMessageCard :id="refmsgid" />
×
25
        <AddToCalendar
26
          v-if="tryst?.calendarLink"
27
          :calendar-link="tryst.calendarLink"
28
          class="mt-2"
29
        />
×
30
        <notice-message
31
          v-if="refmsg.outcomes?.length || refmsg.deleted"
32
          class="mt-2"
33
        >
34
          <v-icon icon="info-circle" />
35
          <span v-if="refmsg.type === 'Offer'">
×
36
            This is no longer available.
37
          </span>
38
          <span v-else> They are no longer looking for this. </span>
39
        </notice-message>
40
        <div v-if="emessage" class="promised-text mt-2">
×
41
          <span
42
            v-if="
×
43
              chatmessage.secondsago < 60 || chatmessage.id > chat.lastmsgseen
44
            "
45
            class="prewrap font-weight-bold"
46
            >{{ emessage }}</span
47
          >
48
          <span v-else class="preline forcebreak">{{ emessage }}</span>
49
        </div>
50
      </div>
51
    </div>
52

53
    <!-- Sent promise (from current user) -->
54
    <div v-else class="promised-message promised-message--mine">
55
      <div v-if="!refmsg" class="text-muted small">
56
        This chat message refers to a post (<v-icon
57
          icon="hashtag"
58
          class="text-muted fa-0-8x"
59
        />{{ chatmessage.refmsgid }}) which has been deleted.
60
      </div>
61
      <div v-else class="promised-wrapper">
62
        <div class="promised-header">
63
          <ProfileImage
64
            :image="me.profile.path"
65
            :name="me.displayname"
66
            class="mr-2 inline"
67
            is-thumbnail
68
            size="sm"
69
          />
70
          <span class="promised-label">
71
            You promised <strong>{{ otheruser.displayname }}</strong
×
72
            >:
73
          </span>
74
        </div>
75
        <ChatMessageCard :id="refmsgid" :show-location="false" />
76
        <p v-if="tryst?.arrangedfor" class="small text-info mt-2 mb-1">
77
          Handover arranged for
78
          <strong
79
            ><DateFormatted :value="tryst.arrangedfor" format="weekdaytime"
80
          /></strong>
81
        </p>
82
        <div v-if="refmsg" class="promised-actions mt-2">
83
          <template v-if="tryst">
×
84
            <AddToCalendar
85
              v-if="tryst?.calendarLink"
86
              :calendar-link="tryst.calendarLink"
87
              class="mr-2 mb-1"
88
            />
89
            <b-button
90
              v-if="refmsg.promisecount && refmsg.availablenow"
×
91
              variant="secondary"
92
              size="sm"
93
              class="mr-2 mb-1"
94
              @click="changeTime"
95
            >
96
              <v-icon icon="pen" />
×
97
              Change time
98
            </b-button>
99
          </template>
100
          <template v-else-if="refmsg.promisecount && refmsg.availablenow">
101
            <b-button
102
              variant="secondary"
103
              size="sm"
104
              class="mr-2 mb-1"
105
              @click="changeTime"
106
            >
107
              <v-icon icon="pen" />
×
108
              Set time
109
            </b-button>
110
          </template>
111
          <b-button
112
            v-if="refmsg.promisecount && refmsg.availablenow"
×
113
            variant="warning"
114
            size="sm"
115
            class="mr-2 mb-1"
116
            @click="unpromise"
117
          >
118
            Unpromise
119
          </b-button>
×
120
          <b-button
121
            v-if="refmsg.availablenow"
122
            variant="primary"
123
            size="sm"
124
            class="mb-1"
125
            @click="outcome('Taken')"
×
126
          >
127
            Mark as TAKEN
128
          </b-button>
×
129
        </div>
×
130
        <notice-message
131
          v-if="refmsg.outcomes?.length || refmsg.deleted"
132
          class="mt-2"
133
        >
134
          <v-icon icon="info-circle" />
135
          <span v-if="refmsg.type === 'Offer'">
×
136
            This is no longer available.
137
          </span>
138
          <span v-else> They are no longer looking for this. </span>
139
        </notice-message>
140
        <p v-else-if="!refmsg?.availablenow" class="text-muted small mt-2">
×
141
          This has now been taken.
142
        </p>
143
        <div v-if="emessage" class="promised-text mt-2">
×
144
          <span
145
            v-if="
×
146
              chatmessage.secondsago < 60 || chatmessage.id > chat.lastmsgseen
147
            "
148
            class="prewrap font-weight-bold"
149
            >{{ emessage }}</span
150
          >
151
          <span v-else class="preline forcebreak">{{ emessage }}</span>
152
        </div>
153
        <PromiseModal
154
          v-if="showPromise"
×
155
          :messages="[refmsg]"
156
          :selected-message="refmsgid"
157
          :users="otheruser ? [otheruser] : []"
×
158
          :selected-user="otheruser ? otheruser.id : null"
×
159
          @hidden="showPromise = false"
×
160
        />
161
      </div>
162
    </div>
163
    <RenegeModal
164
      v-if="showRenege && refmsgid"
×
165
      :messages="[refmsgid]"
166
      :selected-message="refmsgid"
167
      :users="[otheruser]"
168
      :selected-user="otheruser.id"
169
      @hide="fetchMessages"
170
      @hidden="showRenege = false"
×
171
    />
172
    <OutcomeModal
173
      v-if="showOutcome && refmsgid"
×
174
      :id="refmsgid"
175
      :taken-by="takenBy"
176
      :type="outcomeType"
177
      @outcome="fetchMessage"
178
      @hidden="showOutcome = false"
×
179
    />
180
  </div>
181
</template>
182
<script setup>
183
import { ref, defineAsyncComponent } from 'vue'
184
import DateFormatted from './DateFormatted'
185
import { useTrystStore } from '~/stores/tryst'
186
import { fetchOurOffers } from '~/composables/useThrottle'
187
import { useChatStore } from '~/stores/chat'
188
import {
189
  fetchReferencedMessage,
190
  useChatMessageBase,
191
} from '~/composables/useChat'
192
import { useMessageStore } from '~/stores/message'
193
import AddToCalendar from '~/components/AddToCalendar'
194
import ProfileImage from '~/components/ProfileImage'
195
import ChatMessageCard from '~/components/ChatMessageCard'
196

197
const OutcomeModal = defineAsyncComponent(() =>
×
198
  import('~/components/OutcomeModal')
199
)
200

201
const RenegeModal = defineAsyncComponent(() => import('./RenegeModal'))
×
202
const PromiseModal = defineAsyncComponent(() =>
×
203
  import('~/components/PromiseModal')
204
)
205

206
const props = defineProps({
×
207
  chatid: {
208
    type: Number,
209
    required: true,
210
  },
211
  id: {
212
    type: Number,
213
    required: true,
214
  },
215
  last: {
216
    type: Boolean,
217
    required: false,
218
    default: false,
219
  },
220
  pov: {
221
    type: Number,
222
    required: false,
223
    default: null,
224
  },
225
  highlightEmails: {
226
    type: Boolean,
227
    required: false,
228
    default: false,
229
  },
230
})
231

232
// Data properties
233
const showRenege = ref(false)
×
234
const showOutcome = ref(false)
×
235
const outcomeType = ref(null)
×
236
const showPromise = ref(false)
×
237

238
// Stores
239
const trystStore = useTrystStore()
×
240
const chatStore = useChatStore()
×
241
const messageStore = useMessageStore()
×
242

243
// Setup
244
await trystStore.fetch()
×
245
await fetchReferencedMessage(props.chatid, props.id)
×
246

247
// Use the chat base composable
248
const {
×
249
  chat,
250
  chatmessage,
251
  emessage,
252
  refmsgid,
253
  refmsg,
254
  me,
255
  myid,
256
  otheruser,
257
  fetchMessage,
258
} = useChatMessageBase(props.chatid, props.id, props.pov)
259

260
if (refmsgid.value) {
×
261
  useMessageStore().fetch(refmsgid.value)
×
262
}
263

264
// Component-specific computed properties
265
const tryst = computed(() => {
×
266
  return otheruser.value ? trystStore?.getByUser(otheruser.value.id) : null
×
267
})
268

269
const takenBy = computed(() => {
×
270
  let ret = null
×
271

272
  if (otheruser.value) {
×
273
    ret = otheruser.value
×
274
    ret.userid = otheruser.value.id
×
275
    ret.count = 1
×
276
  }
277

278
  return ret
×
279
})
280

281
// Methods
282
function unpromise() {
×
283
  showRenege.value = true
×
284
  fetchOurOffers()
×
285
}
286

287
function changeTime() {
×
288
  showPromise.value = true
×
289
}
290

291
function fetchMessages() {
×
292
  chatStore.fetchMessages(chatmessage.value.chatid)
×
293
}
294

295
async function outcome(type) {
×
296
  await messageStore.fetch(refmsgid.value)
×
297

298
  showOutcome.value = true
×
299
  outcomeType.value = type
×
300
}
301
</script>
302
<style scoped lang="scss">
303
@import 'bootstrap/scss/functions';
304
@import 'bootstrap/scss/variables';
305
@import 'assets/css/_color-vars.scss';
306

307
.chat-message-promised {
308
  max-width: 100%;
309
}
310

311
.promised-message {
312
  width: 100%;
313
}
314

315
.promised-message--mine {
316
  margin-left: auto;
317
}
318

319
.promised-wrapper {
320
  background-color: #ffffff;
321
  border: 1px solid rgba(0, 0, 0, 0.1);
322
  border-radius: 10px;
323
  padding: 12px;
324
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
325
}
326

327
.promised-header {
328
  display: flex;
329
  align-items: center;
330
  margin-bottom: 8px;
331
}
332

333
.promised-label {
334
  font-size: 0.85rem;
335
  color: #333;
336
}
337

338
.promised-actions {
339
  display: flex;
340
  flex-wrap: wrap;
341
  gap: 4px;
342
}
343

344
.promised-text {
345
  font-size: 0.9rem;
346
  padding: 8px;
347
  background: $color-gray--lighter;
348
  border-radius: 8px;
349
}
350
</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