Skip to content

Commit

Permalink
feat(members): render ongoing membership (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtthp authored Jan 2, 2024
1 parent 9313b30 commit 69d8c78
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/i18n/locales/en-GB/members.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"description": "Present for the last time {date}"
},
"membership": {
"current": "{year} membership ongoing",
"last": "Last membership in {year}"
},
"onFetch": {
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/fr-FR/members.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"description": "Présent⸱e pour la dernière fois {date}"
},
"membership": {
"current": "Adhésion {year} en cours",
"last": "Dernière adhésion en {year}"
},
"onFetch": {
Expand Down
8 changes: 5 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ router.beforeEach(async (to, from, next) => {
await (async () => {
// retrieve tokens from query params
if (accessToken) {
await authStore.setAccessToken(accessToken as string);
await authStore.setAccessToken(accessToken as string).catch((error) => {
notificationsStore.addErrorNotification(error);
return Promise.reject(error);
});
}

if (refreshToken) {
Expand All @@ -70,8 +73,7 @@ router.beforeEach(async (to, from, next) => {
}

next();
})().catch((error) => {
notificationsStore.addErrorNotification(error);
})().catch(() => {
// When user has invalid session,
// set redirectPath to allow loging page to redirect user on desired page afterwards
next({
Expand Down
25 changes: 13 additions & 12 deletions src/views/Private/Members/MembersDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
class="h-16 w-16 rounded-full bg-gray-200"
:src="state.member.picture" />
<span
v-if="!!state.member.lastSeen && dayjs().isSame(state.member.lastSeen, 'hour')"
v-if="
!!state.member.lastSeen && dayjs().diff(state.member.lastSeen, 'hour', true) < 1
"
class="absolute bottom-0 right-0 block h-4 w-4 rounded-full bg-green-400 ring-2 ring-white" />
</div>
</div>
Expand All @@ -48,9 +50,7 @@
</time>
</template>
</i18n-t>
<div
v-if="state.member.balance < 0 || isMembershipNonCompliant(state.member)"
class="mt-1 flex flex-row flex-wrap items-center gap-2">
<div class="mt-1 flex flex-row flex-wrap items-center gap-2">
<span
v-if="state.member.balance < 0"
class="shrink basis-0 whitespace-nowrap rounded-full bg-red-500/10 px-2 py-0.5 text-center text-xs leading-6 text-red-400 ring-1 ring-inset ring-red-500/20">
Expand All @@ -61,7 +61,14 @@
}}
</span>
<span
v-if="isMembershipNonCompliant(state.member)"
v-if="state.member.membershipOk"
class="shrink basis-0 whitespace-nowrap rounded-full bg-indigo-500/10 px-2 py-0.5 text-center text-xs leading-6 text-indigo-400 ring-1 ring-inset ring-indigo-500/20">
{{
$t('members.detail.membership.current', { year: state.member.lastMembership })
}}
</span>
<span
v-else
class="shrink basis-0 whitespace-nowrap rounded-full bg-neutral-500/10 px-2 py-0.5 text-center text-xs leading-6 text-neutral-500 ring-1 ring-inset ring-neutral-500/20">
{{ $t('members.detail.membership.last', { year: state.member.lastMembership }) }}
</span>
Expand Down Expand Up @@ -324,13 +331,7 @@ import LoadingSpinner from '@/components/LoadingSpinner.vue';
import SideDialog from '@/components/layout/SideDialog.vue';
import { handleSilentError, parseErrorText } from '@/helpers/errors';
import { ROUTE_NAMES } from '@/router/names';
import {
Attendance,
Member,
getMember,
getMemberPresences,
isMembershipNonCompliant,
} from '@/services/api/members';
import { Attendance, Member, getMember, getMemberPresences } from '@/services/api/members';
import { Subscription, getAllMemberSubscriptions } from '@/services/api/subscriptions';
import { Ticket, getAllMemberTickets } from '@/services/api/tickets';
import { useNotificationsStore } from '@/store/notifications';
Expand Down
2 changes: 1 addition & 1 deletion src/views/Private/Members/MembersList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
class="h-5 w-5 shrink-0 text-gray-400"
:path="mdiSort"
type="mdi" />
<span class="ml-2 whitespace-nowrap">
<span class="ml-2 whitespace-nowrap max-sm:hidden">
{{
$t('members.list.sort.label', {
...(sort && {
Expand Down
53 changes: 31 additions & 22 deletions src/views/Private/Members/MembersListCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,41 @@
<template v-if="member">
<img alt="" class="h-12 w-12 rounded-full bg-gray-200" :src="member.picture" />
<span
v-if="!!member.lastSeen && dayjs().isSame(member.lastSeen, 'hour')"
v-if="!!member.lastSeen && dayjs().diff(member.lastSeen, 'hour', true) < 1"
class="absolute bottom-0 right-0 block h-3 w-3 rounded-full bg-green-400 ring-2 ring-white" />
</template>
<div v-else-if="loading" class="h-12 w-12 rounded-full bg-slate-200" />
</div>
<div class="flex min-w-0 flex-1 flex-row gap-4 px-4">
<div class="flex shrink grow basis-0 flex-col overflow-hidden">
<div class="flex min-w-0 flex-1 flex-row gap-3 pl-4">
<div class="flex shrink grow basis-0 flex-col items-start overflow-hidden">
<template v-if="member">
<p class="shrink-0 truncate font-medium text-indigo-600 sm:text-sm">
{{ [member.firstName, member.lastName].filter(Boolean).join(' ') }}
{{ fullname }}
</p>

<div class="flex min-h-7 flex-row gap-1">
<p class="flex items-center text-sm text-gray-500">
<div :class="['flex min-h-7 w-full flex-row gap-1', !fullname && 'flex-wrap']">
<p
class="flex max-w-max shrink grow basis-0 items-center overflow-hidden text-sm text-gray-500">
<span class="truncate">{{ member.email }}</span>
</p>
<span
v-if="member.balance < 0"
class="shrink basis-0 whitespace-nowrap rounded-full bg-red-500/10 px-2 py-0.5 text-center text-xs leading-6 text-red-400 ring-1 ring-inset ring-red-500/20">
{{
$t('members.detail.orders.tickets.overconsumed', {
count: Math.abs(member.balance),
})
}}
</span>
<span
v-if="isMembershipNonCompliant(member)"
class="shrink basis-0 whitespace-nowrap rounded-full bg-neutral-500/10 px-2 py-0.5 text-center text-xs leading-6 text-neutral-500 ring-1 ring-inset ring-neutral-500/20">
{{ $t('members.detail.membership.last', { year: member.lastMembership }) }}
</span>
<div
v-if="member.balance < 0 || isMembershipNonCompliant(member)"
class="flex shrink flex-row items-center gap-1">
<span
v-if="member.balance < 0"
class="shrink basis-0 whitespace-nowrap rounded-full bg-red-500/10 px-2 py-0.5 text-center text-xs leading-6 text-red-400 ring-1 ring-inset ring-red-500/20">
{{
$t('members.detail.orders.tickets.overconsumed', {
count: Math.abs(member.balance),
})
}}
</span>
<span
v-if="isMembershipNonCompliant(member)"
class="shrink basis-0 whitespace-nowrap rounded-full bg-neutral-500/10 px-2 py-0.5 text-center text-xs leading-6 text-neutral-500 ring-1 ring-inset ring-neutral-500/20">
{{ $t('members.detail.membership.last', { year: member.lastMembership }) }}
</span>
</div>
</div>
</template>
<template v-else-if="loading">
Expand Down Expand Up @@ -67,9 +72,9 @@
<script setup lang="ts">
import { MemberListItem, isMembershipNonCompliant } from '@/services/api/members';
import dayjs from 'dayjs';
import { PropType } from 'vue';
import { PropType, computed } from 'vue';
defineProps({
const props = defineProps({
member: {
type: Object as PropType<MemberListItem>,
default: null,
Expand All @@ -79,4 +84,8 @@ defineProps({
default: false,
},
});
const fullname = computed<string>(() =>
[props.member?.firstName, props.member?.lastName].filter(Boolean).join(' '),
);
</script>

0 comments on commit 69d8c78

Please sign in to comment.