2024-09-12 19:07:49 +02:00
|
|
|
|
<template>
|
2024-11-27 13:51:59 +01:00
|
|
|
|
<main class="flex flex-col">
|
|
|
|
|
|
<header class="flex">
|
|
|
|
|
|
<h2 id="tabslist" class="sr-only">Status</h2>
|
|
|
|
|
|
<Tabs :tabs="tabs" @update:currentTab="changeTab" />
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="btn"
|
|
|
|
|
|
:disabled="!sortedNotifications.length"
|
|
|
|
|
|
@click="readAll()"
|
|
|
|
|
|
>
|
|
|
|
|
|
Marquer tout come lu
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</header>
|
2024-10-29 17:26:23 +01:00
|
|
|
|
<div
|
2024-10-30 11:12:21 +01:00
|
|
|
|
v-if="sortedNotifications.length === 0"
|
2024-10-29 17:26:23 +01:00
|
|
|
|
class="flex flex-col justify-center | text-grey-700 | absolute inset-0 -z-1"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
|
width="40"
|
|
|
|
|
|
height="40"
|
|
|
|
|
|
viewBox="0 0 40 40"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M23.7 28.925C23.4895 30.6616 22.625 32.2526 21.2825 33.3741C19.94 34.4955 18.2205 35.0631 16.4742 34.9611C14.7279 34.8591 13.0861 34.0953 11.8832 32.8252C10.6804 31.5551 10.0069 29.8743 10 28.125V24.15M34.6 32.675L5.425 22.5C4.94896 22.3339 4.53427 22.0278 4.23534 21.6218C3.93642 21.2158 3.76724 20.7289 3.75 20.225V17.5C3.75206 16.9832 3.91423 16.4798 4.21418 16.0589C4.51414 15.6381 4.93715 15.3205 5.425 15.15L34.6 5.00001C34.7873 4.93673 34.987 4.91879 35.1825 4.94766C35.3781 4.97653 35.5641 5.05137 35.7251 5.16606C35.8862 5.28074 36.0177 5.43199 36.109 5.60738C36.2002 5.78277 36.2485 5.9773 36.25 6.17501V31.5C36.2485 31.6977 36.2002 31.8922 36.109 32.0676C36.0177 32.243 35.8862 32.3943 35.7251 32.5089C35.5641 32.6236 35.3781 32.6985 35.1825 32.7273C34.987 32.7562 34.7873 32.7383 34.6 32.675Z"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="1.25"
|
|
|
|
|
|
stroke-linecap="round"
|
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
|
/>
|
2024-09-17 17:22:58 +02:00
|
|
|
|
</svg>
|
|
|
|
|
|
<p>Vous n’avez pas de nouvelles notifications</p>
|
|
|
|
|
|
</div>
|
2024-10-29 17:26:23 +01:00
|
|
|
|
<section v-else class="notifications | flow">
|
2024-10-30 11:12:21 +01:00
|
|
|
|
<template
|
|
|
|
|
|
v-for="notification in sortedNotifications"
|
|
|
|
|
|
:key="notification.id"
|
|
|
|
|
|
>
|
2024-11-18 16:21:07 +01:00
|
|
|
|
<article
|
|
|
|
|
|
class="notification | bg-white rounded-lg | p-16 | flow"
|
|
|
|
|
|
:data-status="notification.isRead ? 'read' : 'unread'"
|
|
|
|
|
|
:data-type="notification.type"
|
2024-10-29 17:26:23 +01:00
|
|
|
|
>
|
2024-11-18 16:21:07 +01:00
|
|
|
|
<router-link
|
|
|
|
|
|
v-if="currentTab === 'all' || !notification.isRead"
|
2024-12-16 17:25:52 +01:00
|
|
|
|
:to="toPath(notification.location.href)"
|
2024-10-29 17:26:23 +01:00
|
|
|
|
>
|
|
|
|
|
|
<header>
|
|
|
|
|
|
<p class="flex">
|
|
|
|
|
|
<strong
|
|
|
|
|
|
class="notification__type | font-medium text-primary"
|
|
|
|
|
|
:data-icon="notification.type"
|
|
|
|
|
|
>Nouveau
|
|
|
|
|
|
{{
|
|
|
|
|
|
notification.type === "comment" ? "commentaire" : "contenu"
|
|
|
|
|
|
}}</strong
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="notification__client | text-grey-700">{{
|
2024-11-18 12:00:19 +01:00
|
|
|
|
notification.location.project.title
|
2024-10-29 17:26:23 +01:00
|
|
|
|
}}</span>
|
|
|
|
|
|
<time
|
|
|
|
|
|
datetime=""
|
|
|
|
|
|
class="notification__date | text-grey-700 | ml-auto"
|
2024-11-18 12:20:51 +01:00
|
|
|
|
>{{ formatDate(notification) }}</time
|
2024-10-29 17:26:23 +01:00
|
|
|
|
>
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
<p
|
2024-12-16 17:25:52 +01:00
|
|
|
|
v-if="notification.type"
|
2024-10-29 17:26:23 +01:00
|
|
|
|
class="notification__body | text-md font-medium | line-clamp"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ notification.text }}
|
|
|
|
|
|
</p>
|
2024-11-18 16:21:07 +01:00
|
|
|
|
</router-link>
|
|
|
|
|
|
</article>
|
2024-10-29 17:26:23 +01:00
|
|
|
|
</template>
|
|
|
|
|
|
<!-- <article
|
2024-10-29 13:02:03 +01:00
|
|
|
|
class="notification | bg-white rounded-lg | p-16 | flow"
|
|
|
|
|
|
data-status="read"
|
|
|
|
|
|
data-type="content"
|
|
|
|
|
|
>
|
|
|
|
|
|
<header>
|
|
|
|
|
|
<p class="flex">
|
2024-10-29 17:26:23 +01:00
|
|
|
|
<strong
|
|
|
|
|
|
class="notification__type | font-medium text-primary"
|
|
|
|
|
|
data-icon="content"
|
|
|
|
|
|
>Nouveau contenu</strong
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="notification__client | text-grey-700"></span>
|
|
|
|
|
|
<time
|
|
|
|
|
|
datetime=""
|
|
|
|
|
|
class="notification__date | text-grey-700 | ml-auto"
|
|
|
|
|
|
>Hier</time
|
|
|
|
|
|
>
|
2024-10-29 13:02:03 +01:00
|
|
|
|
</p>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
<p class="notification__body | text-md font-medium | line-clamp">
|
|
|
|
|
|
Proposition 2
|
|
|
|
|
|
</p>
|
2024-10-29 17:26:23 +01:00
|
|
|
|
</article> -->
|
2024-10-29 13:02:03 +01:00
|
|
|
|
</section>
|
2024-09-17 17:22:58 +02:00
|
|
|
|
</main>
|
2024-09-12 19:07:49 +02:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2024-10-29 17:26:23 +01:00
|
|
|
|
import dayjs from "dayjs";
|
|
|
|
|
|
import "dayjs/locale/fr";
|
2024-09-12 19:07:49 +02:00
|
|
|
|
import Tabs from "../components/Tabs.vue";
|
|
|
|
|
|
import { useUserStore } from "../stores/user";
|
|
|
|
|
|
import { ref, computed } from "vue";
|
2024-09-17 17:22:58 +02:00
|
|
|
|
import { storeToRefs } from "pinia";
|
2024-11-18 13:45:40 +01:00
|
|
|
|
import { useApiStore } from "../stores/api";
|
2024-09-12 19:07:49 +02:00
|
|
|
|
|
2024-10-29 17:26:23 +01:00
|
|
|
|
dayjs.locale("fr");
|
|
|
|
|
|
|
2024-11-18 13:45:40 +01:00
|
|
|
|
const userStore = useUserStore();
|
2024-10-30 10:56:11 +01:00
|
|
|
|
const { notifications } = storeToRefs(useUserStore());
|
2024-11-18 13:45:40 +01:00
|
|
|
|
const api = useApiStore();
|
2024-09-12 19:07:49 +02:00
|
|
|
|
const currentTab = ref("all");
|
|
|
|
|
|
const tabs = computed(() => {
|
|
|
|
|
|
return [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Tout",
|
|
|
|
|
|
id: "all",
|
|
|
|
|
|
icon: null,
|
|
|
|
|
|
count: null,
|
|
|
|
|
|
isActive: currentTab.value === "all",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Non lu",
|
|
|
|
|
|
id: "unread",
|
|
|
|
|
|
icon: null,
|
|
|
|
|
|
count: null,
|
|
|
|
|
|
isActive: currentTab.value === "unread",
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2024-10-30 11:12:21 +01:00
|
|
|
|
const sortedNotifications = computed(() => {
|
2024-11-22 09:53:58 +01:00
|
|
|
|
return [...notifications.value].sort((a, b) => {
|
|
|
|
|
|
return dayjs(b.date).diff(dayjs(a.date));
|
2024-10-30 11:12:21 +01:00
|
|
|
|
});
|
2024-10-30 10:56:11 +01:00
|
|
|
|
});
|
2024-10-29 17:26:23 +01:00
|
|
|
|
|
2024-09-12 19:07:49 +02:00
|
|
|
|
function changeTab(newValue) {
|
|
|
|
|
|
currentTab.value = newValue;
|
|
|
|
|
|
}
|
2024-11-18 12:20:51 +01:00
|
|
|
|
|
|
|
|
|
|
function formatDate(notification) {
|
|
|
|
|
|
const notificationDigitalDate = parseInt(
|
|
|
|
|
|
dayjs(notification.date).format("YYYYMMDD")
|
|
|
|
|
|
);
|
|
|
|
|
|
const todayDigitalDate = parseInt(dayjs().format("YYYYMMDD"));
|
|
|
|
|
|
const isToday = notificationDigitalDate === todayDigitalDate;
|
|
|
|
|
|
|
|
|
|
|
|
if (isToday) {
|
2024-11-18 16:21:07 +01:00
|
|
|
|
return dayjs(notification.date).format("HH:mm");
|
2024-11-18 12:20:51 +01:00
|
|
|
|
} else if (todayDigitalDate === notificationDigitalDate + 1) {
|
|
|
|
|
|
return "hier";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return dayjs(notification.date).format("DD MMM YY");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-18 13:45:40 +01:00
|
|
|
|
|
|
|
|
|
|
function readAll() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
api.readAllNotifications();
|
|
|
|
|
|
userStore.readAllNotifications();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.log("Could not read all notifications : ", error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-12-16 17:25:52 +01:00
|
|
|
|
|
|
|
|
|
|
function toPath(string) {
|
|
|
|
|
|
return string.replace(window.location.origin, "");
|
|
|
|
|
|
}
|
2024-09-12 19:07:49 +02:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
2024-12-11 14:26:39 +01:00
|
|
|
|
main {
|
|
|
|
|
|
max-width: 52.5rem;
|
|
|
|
|
|
margin: auto;
|
|
|
|
|
|
}
|
2024-11-27 13:51:59 +01:00
|
|
|
|
main > header {
|
|
|
|
|
|
flex-wrap: nowrap;
|
2024-09-12 19:07:49 +02:00
|
|
|
|
}
|
2024-12-11 14:26:39 +01:00
|
|
|
|
main > header [role="tablist"] {
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
}
|
2024-10-29 13:02:03 +01:00
|
|
|
|
|
|
|
|
|
|
/* Notifications */
|
2024-11-15 16:37:18 +01:00
|
|
|
|
.notifications {
|
|
|
|
|
|
--flow-space: var(--space-16);
|
|
|
|
|
|
}
|
2024-10-29 13:02:03 +01:00
|
|
|
|
.notification {
|
|
|
|
|
|
--flow-space: var(--space-12);
|
|
|
|
|
|
font-size: var(--text-sm);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification[data-status="unread"]::after {
|
2024-10-29 17:26:23 +01:00
|
|
|
|
content: "";
|
2024-10-29 13:02:03 +01:00
|
|
|
|
display: inline-block;
|
2024-10-29 17:26:23 +01:00
|
|
|
|
width: 0.5rem;
|
|
|
|
|
|
height: 0.5rem;
|
2024-10-29 13:02:03 +01:00
|
|
|
|
outline: 2px solid var(--color-white);
|
|
|
|
|
|
background: var(--color-primary);
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification p {
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification header p {
|
|
|
|
|
|
column-gap: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification__type {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification__type::before {
|
|
|
|
|
|
margin-right: var(--space-8);
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification__client {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.notification__client::before {
|
2024-10-29 17:26:23 +01:00
|
|
|
|
content: "";
|
2024-10-29 13:02:03 +01:00
|
|
|
|
display: inline-block;
|
|
|
|
|
|
width: 3px;
|
|
|
|
|
|
height: 3px;
|
|
|
|
|
|
background: var(--color-grey-700);
|
|
|
|
|
|
border-radius: 50%;
|
2024-10-29 17:26:23 +01:00
|
|
|
|
margin: 0.2em 0.5em;
|
2024-10-29 13:02:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
.notification__body {
|
|
|
|
|
|
--line-clamp: 2;
|
|
|
|
|
|
}
|
2024-09-12 19:07:49 +02:00
|
|
|
|
</style>
|