Changes to import and notifications
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, onMounted } from "vue";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { usePage, Link } from "@inertiajs/vue3";
|
||||
import Dropdown from "@/Components/Dropdown.vue";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
@@ -10,6 +10,10 @@ const due = computed(
|
||||
() => page.props.notifications?.dueToday || { count: 0, items: [], date: null }
|
||||
);
|
||||
|
||||
// Local, optimistically-updated list of items and derived count
|
||||
const items = ref([]);
|
||||
const count = computed(() => items.value.length);
|
||||
|
||||
function fmtDate(d) {
|
||||
if (!d) return "";
|
||||
try {
|
||||
@@ -37,16 +41,43 @@ function fmtEUR(value) {
|
||||
// Replace non-breaking space with normal space for consistency
|
||||
return formatted.replace("\u00A0", " ");
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log(due.value);
|
||||
items.value = [...(due.value.items || [])];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => due.value.items,
|
||||
(val) => {
|
||||
items.value = [...(val || [])];
|
||||
}
|
||||
);
|
||||
|
||||
async function markRead(item) {
|
||||
const idx = items.value.findIndex((i) => i.id === item.id);
|
||||
if (idx === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimistically remove
|
||||
const removed = items.value.splice(idx, 1)[0];
|
||||
|
||||
try {
|
||||
await window.axios.post(route("notifications.activity.read"), {
|
||||
activity_id: item.id,
|
||||
});
|
||||
} catch (e) {
|
||||
// Rollback on failure
|
||||
items.value.splice(idx, 0, removed);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dropdown
|
||||
align="right"
|
||||
width="72"
|
||||
:content-classes="['py-1', 'bg-white', 'max-h-96', 'overflow-auto']"
|
||||
:content-classes="['p-0', 'bg-white', 'max-h-96', 'overflow-hidden']"
|
||||
>
|
||||
<template #trigger>
|
||||
<button
|
||||
@@ -56,48 +87,76 @@ onMounted(() => {
|
||||
>
|
||||
<FontAwesomeIcon :icon="faBell" class="w-5 h-5" />
|
||||
<span
|
||||
v-if="due.count"
|
||||
v-if="count"
|
||||
class="absolute -top-1 -right-1 inline-flex items-center justify-center h-5 min-w-[1.25rem] px-1 rounded-full text-[11px] bg-red-600 text-white"
|
||||
>{{ due.count }}</span
|
||||
>{{ count }}</span
|
||||
>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<div class="px-3 py-2 text-xs text-gray-400 border-b">Obljube zapadejo jutri</div>
|
||||
<div class="px-3 py-2 text-xs text-gray-400 border-b sticky top-0 bg-white z-10 flex items-center justify-between">
|
||||
<span>Zapadejo danes</span>
|
||||
<Link :href="route('notifications.unread')" class="text-indigo-600 hover:text-indigo-700">Vsa obvestila</Link>
|
||||
</div>
|
||||
<!-- Scrollable content area with max height -->
|
||||
<div class="max-h-96 overflow-y-auto">
|
||||
<div v-if="!due.count" class="px-3 py-3 text-sm text-gray-500">
|
||||
<div class="max-h-80 overflow-auto">
|
||||
<div v-if="!count" class="px-3 py-3 text-sm text-gray-500">
|
||||
Ni zapadlih aktivnosti danes.
|
||||
</div>
|
||||
<ul v-else class="divide-y">
|
||||
<li
|
||||
v-for="item in due.items"
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
class="px-3 py-2 text-sm flex items-start gap-2"
|
||||
>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-medium text-gray-800 truncate">
|
||||
Pogodba:
|
||||
<Link
|
||||
v-if="item.contract?.client_case?.uuid"
|
||||
:href="
|
||||
route('clientCase.show', {
|
||||
client_case: item.contract.client_case.uuid,
|
||||
})
|
||||
"
|
||||
class="text-indigo-600 hover:text-indigo-700 hover:underline"
|
||||
>
|
||||
{{ item.contract?.reference || "—" }}
|
||||
</Link>
|
||||
<span v-else>{{ item.contract?.reference || "—" }}</span>
|
||||
<template v-if="item.contract?.uuid">
|
||||
Pogodba:
|
||||
<Link
|
||||
v-if="item.contract?.client_case?.uuid"
|
||||
:href="
|
||||
route('clientCase.show', {
|
||||
client_case: item.contract.client_case.uuid,
|
||||
})
|
||||
"
|
||||
class="text-indigo-600 hover:text-indigo-700 hover:underline"
|
||||
>
|
||||
{{ item.contract?.reference || "—" }}
|
||||
</Link>
|
||||
<span v-else>{{ item.contract?.reference || "—" }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
Primer:
|
||||
<Link
|
||||
v-if="item.client_case?.uuid"
|
||||
:href="
|
||||
route('clientCase.show', { client_case: item.client_case.uuid })
|
||||
"
|
||||
class="text-indigo-600 hover:text-indigo-700 hover:underline"
|
||||
>
|
||||
{{ item.client_case?.person?.full_name || "—" }}
|
||||
</Link>
|
||||
<span v-else>{{ item.client_case?.person?.full_name || "—" }}</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="text-gray-600 truncate">
|
||||
<div class="text-gray-600 truncate" v-if="item.contract">
|
||||
{{ fmtEUR(item.contract?.account?.balance_amount) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-gray-500 whitespace-nowrap">
|
||||
{{ fmtDate(item.due_date) }}
|
||||
<div class="flex flex-col items-end gap-1">
|
||||
<div class="text-xs text-gray-500 whitespace-nowrap">
|
||||
{{ fmtDate(item.due_date) }}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="text-[11px] text-gray-400 hover:text-gray-600"
|
||||
@click.stop="markRead(item)"
|
||||
title="Skrij obvestilo"
|
||||
>
|
||||
Skrij
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user