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

Freegle / iznik-nuxt3 / 6bd7579a-30c4-40ea-9a8a-1291e094e81e

01 Oct 2025 01:42PM UTC coverage: 34.694% (-9.9%) from 44.618%
6bd7579a-30c4-40ea-9a8a-1291e094e81e

push

circleci

edwh
MT: In /map, don't show the centre points for groups which are not supposed to show on the map.

1053 of 3928 branches covered (26.81%)

Branch coverage included in aggregate %.

2722 of 6953 relevant lines covered (39.15%)

37.76 hits per line

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

51.04
/components/MyPostsPostsList.vue
1
<template>
2
  <b-card
3
    class="mt-2"
4
    border-variant="info"
5
    header="info"
6
    header-bg-variant="info"
7
    header-text-variant="white"
8
    no-body
9
  >
10
    <template #header>
11
      <div class="d-flex justify-content-between">
12
        <span v-if="oldPosts.length > 0">
13
          <span v-if="!showOldPosts">
14
            <b-button variant="secondary" @click="toggleShowOldPosts">
15
              Show {{ formattedOldPostsCount }}
16
            </b-button>
17
          </span>
18
          <span v-else>
19
            <b-button variant="secondary" @click="toggleShowOldPosts">
20
              Hide {{ formattedOldPostsCount }}
21
            </b-button>
22
          </span>
23
        </span>
24
      </div>
25
    </template>
26

27
    <b-card-body class="p-1 p-lg-3">
28
      <b-card-text class="text-center">
29
        <div
30
          v-if="upcomingTrysts.length > 0"
31
          class="mt-2 mb-3 border border-info p-2"
32
        >
33
          <h3 class="header--size4 text-start">Your upcoming collections:</h3>
34
          <div
35
            v-for="tryst in upcomingTrysts"
36
            :key="'tryst-' + tryst.id"
37
            variant="info"
38
            class="text-start"
39
          >
40
            <v-icon icon="calendar-alt" class="pt-1" />&nbsp;
41
            <span class="font-weight-bold">{{ tryst.trystdate }}</span>
42
            &nbsp;{{ tryst.name }} collecting&nbsp;<em>{{ tryst.subject }}</em>
43
          </div>
44
        </div>
45
        <div v-if="visiblePosts.length > 0">
46
          <div
47
            v-for="post in visiblePosts"
48
            :key="'post-' + post.id"
49
            class="p-0 text-start mt-1"
50
          >
51
            <Suspense>
52
              <MyMessage
53
                :id="post.id"
54
                :show-old="showOldPosts"
55
                :expand="defaultExpanded"
56
                class="minheight"
57
              />
58
              <template #fallback>
59
                <div class="w-100 d-flex justify-content-center text-center">
60
                  <client-only>
61
                    <b-img lazy src="/loader.gif" alt="Loading" width="100px" />
62
                  </client-only>
63
                </div>
64
              </template>
65
            </Suspense>
66
          </div>
67
          <b-img
68
            v-if="loading"
69
            lazy
70
            src="/loader.gif"
71
            alt="Loading..."
72
            width="100px"
73
          />
74
          <InfiniteLoading
75
            :distance="scrollboxHeight"
76
            @infinite="emit('load-more', $event)"
77
          />
78
        </div>
79
        <div v-else>
80
          <b-row>
81
            <b-col>
82
              <p>You have no active posts.</p>
83
            </b-col>
84
          </b-row>
85
          <b-row>
86
            <b-col class="text-center">
87
              <template v-if="props.type === 'Offer'">
88
                <b-button to="/give" class="mt-1" size="lg" variant="primary">
89
                  <v-icon icon="gift" />&nbsp;OFFER something
90
                </b-button>
91
              </template>
92
              <template v-else-if="props.type === 'Wanted'">
93
                <b-button to="/find" class="mt-1" size="lg" variant="primary">
94
                  <v-icon icon="shopping-cart" />&nbsp;Ask for something
95
                </b-button>
96
              </template>
97
            </b-col>
98
          </b-row>
99
        </div>
100
      </b-card-text>
101
    </b-card-body>
102
  </b-card>
103
</template>
104
<script setup>
105
import pluralize from 'pluralize'
106
import dayjs from 'dayjs'
107
import MyMessage from '~/components/MyMessage.vue'
108
import InfiniteLoading from '~/components/InfiniteLoading.vue'
109
import { useMessageStore } from '~/stores/message'
110
import { useUserStore } from '~/stores/user'
111
import { useTrystStore } from '~/stores/tryst'
112

113
const messageStore = useMessageStore()
6✔
114
const userStore = useUserStore()
6✔
115
const trystStore = useTrystStore()
6✔
116

117
const props = defineProps({
6✔
118
  posts: { type: Array, required: true },
119
  postIds: { type: Array, required: false },
120
  loading: { type: Boolean, required: true },
121
  defaultExpanded: { type: Boolean, required: true },
122
  show: { type: Number, required: true },
123
})
124

125
const emit = defineEmits(['load-more'])
6✔
126

127
const scrollboxHeight = ref(1000)
6✔
128

129
const showOldPosts = ref(false)
6✔
130
function toggleShowOldPosts() {
×
131
  showOldPosts.value = !showOldPosts.value
×
132
}
133

6✔
134
// old posts are those without an outcome
135
const oldPosts = computed(() => {
136
  return props.posts.filter((post) => post.hasoutcome)
12✔
137
})
138

139
const formattedOldPostsCount = computed(() => {
6✔
140
  return pluralize(`old post`, oldPosts.value.length, true)
×
141
})
142

143
const activePosts = computed(() => {
6✔
144
  return props.posts.filter((post) => !post.hasoutcome)
12✔
145
})
146

147
const postIds = computed(() => {
6✔
148
  return props.posts.map((post) => post.id)
12✔
149
})
150

151
watch(postIds, (newIds, oldIds) => {
6✔
152
  // Fetch new messages when postIds change
153
  if (oldIds && newIds.length !== oldIds.length) {
6✔
154
    const newPostIds = newIds.filter(id => !oldIds.includes(id))
3✔
155
    newPostIds.forEach((id) => {
3✔
156
      if (!messageStore.byId(id)) {
3!
157
        messageStore.fetch(id)
×
158
      }
159
    })
160
  }
161
})
162

163
watch(activePosts, (newVal) => {
6✔
164
  // For messages which are promised and not successful, we need to trigger a fetch.  This is so
165
  // that we can correctly show the upcoming collections.
166
  newVal.forEach((post) => {
6✔
167
    if (
3!
168
      post.type === 'Offer' &&
6!
169
      post.promised &&
170
      !post.hasoutcome &&
171
      !messageStore.byId(post.id)
172
    ) {
173
      messageStore.fetch(post.id)
×
174
    }
175
  })
176
})
177

178
const visiblePosts = computed(() => {
6✔
179
  let posts = showOldPosts.value ? props.posts : activePosts.value
12!
180
  posts = posts || []
12!
181

182
  return posts.toSorted((a, b) => {
12✔
183
    // promised items first, then by most recently posted
184
    if (!showOldPosts.value && a.promised && !b.promised) {
×
185
      return -1
×
186
    } else if (!showOldPosts.value && b.promised && !a.promised) {
×
187
      return 1
×
188
    } else {
189
      return new Date(b.arrival).getTime() - new Date(a.arrival).getTime()
×
190
    }
191
  })
192
})
193

194
const upcomingTrysts = computed(() => {
6✔
195
  const ret = []
18✔
196

197
  activePosts.value.forEach((post) => {
18✔
198
    const message = messageStore.byId(post.id)
9✔
199
    if (post.type === 'Offer' && message?.promises?.length) {
9!
200
      message.promises.forEach((p) => {
×
201
        const user = userStore?.byId(p.userid)
×
202

203
        if (user) {
×
204
          const tryst = trystStore?.getByUser(p.userid)
×
205

206
          // If tryst.arrangedfor is in the future or within the last hour
207
          if (
×
208
            tryst &&
×
209
            new Date(tryst.arrangedfor).getTime() >
210
              new Date().getTime() - 60 * 60 * 1000
211
          ) {
212
            const date = tryst
×
213
              ? dayjs(tryst.arrangedfor).format('dddd Do HH:mm a')
214
              : null
215

216
            ret.push({
×
217
              id: p.userid,
218
              name: user.displayname,
219
              tryst,
220
              trystdate: date,
221
              subject: message.subject,
222
            })
223
          }
224
        }
225
      })
226
    }
227
  })
228

229
  return ret.toSorted((a, b) => {
18✔
230
    return (
×
231
      new Date(a.tryst.arrangedfor).getTime() -
232
      new Date(b.tryst.arrangedfor).getTime()
233
    )
234
  })
235
})
236
</script>
237
<style scoped>
238
.minheight {
239
  min-height: 200px;
240
}
241
</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