This commit is contained in:
2026-05-09 20:40:27 +02:00
parent 94e2b8bd47
commit 0b49ac4b48
8 changed files with 175 additions and 141 deletions

View File

@@ -2,63 +2,26 @@
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { useCampaignService } from '~/services/Campaign.js';
import { FetchCampaignNotes, PushNote, TotalNotes } from '~/services/Content';
import { emitter } from '~/services/Emitter';
import Server from '~/services/Server';
const { Campaign } = useCampaignService();
const notes = ref([]);
const loadingNotes = ref(false);
const notesError = ref('');
const sidebarCollapsed = ref(false);
const selectedTool = ref('');
const campaignId = computed(() => {
return Campaign.value?._id ?? Campaign.value?.id ?? null;
});
const notesMeta = computed(() => {
const count = notes.value.length;
const count = TotalNotes.value.length;
return `${count} ${count === 1 ? 'note' : 'notes'}`;
});
async function fetchCampaignNotes() {
if (!campaignId.value) {
notes.value = [];
notesError.value = '';
return;
}
loadingNotes.value = true;
notesError.value = '';
try {
const response = await Server().get('/note/list', {
params: {
campaign: campaignId.value
}
});
if (response.data.status !== 'ok') {
notes.value = [];
notesError.value = response.data.msg ?? 'Unable to load notes.';
return;
}
notes.value = response.data.notes.map((note) => {
return {
key: note._id,
title: note.title,
text: note.content ?? '',
date: note.date
};
});
} catch (error) {
notes.value = [];
notesError.value = 'Unable to load notes.';
} finally {
loadingNotes.value = false;
}
}
function toggleSidebar() {
sidebarCollapsed.value = !sidebarCollapsed.value;
}
@@ -89,7 +52,7 @@ async function createNote() {
function openNote(note) {
emitter.emit('push-note', note);
PushNote(note);
}
function handleNoteCreated(note) {
@@ -109,14 +72,16 @@ function handleNoteCreated(note) {
date: note.date
};
notes.value = notes.value.filter((currentNote) => {
TotalNotes.value = TotalNotes.value.filter((currentNote) => {
return currentNote.key !== createdNote.key;
});
notes.value.unshift(createdNote);
TotalNotes.value.unshift(createdNote);
openNote(createdNote);
}
onMounted(() => {
selectedTool.value = 'notes';
FetchCampaignNotes();
emitter.on('note-created', handleNoteCreated);
});
@@ -125,13 +90,13 @@ onUnmounted(() => {
});
watch(Campaign, () => {
fetchCampaignNotes();
FetchCampaignNotes();
}, { immediate: true });
</script>
<template>
<div class="sidebar-shell">
<nav class="sidebar-actions" aria-label="Campaign tools">
<nav class="sidebar-tools" aria-label="Campaign tools">
<button
class="sidebar-action"
type="button"
@@ -152,27 +117,43 @@ watch(Campaign, () => {
<button
class="sidebar-action"
type="button"
@click="createNote"
:disabled="!Campaign"
title="New note"
aria-label="New note"
@click="selectedTool = 'notes'"
:class="{ active: selectedTool === 'notes' }"
>
<img class="sidebar-action-icon" src="/icons/iconoir/regular/plus.svg" alt="" aria-hidden="true">
</button>
<button
class="sidebar-action"
type="button"
@click="fetchCampaignNotes"
:disabled="!Campaign || loadingNotes"
title="Refresh notes"
aria-label="Refresh notes"
>
<img class="sidebar-action-icon" src="/icons/iconoir/regular/refresh.svg" alt="" aria-hidden="true">
<img
class="sidebar-action-icon"
:src="'/icons/iconoir/regular/bookmark-book.svg'"
alt=""
aria-hidden="true"
>
</button>
</nav>
<aside class="notes-sidebar" :class="{ collapsed: sidebarCollapsed }">
<div class="sidebar-actions">
<button
class="sidebar-action"
type="button"
@click="createNote"
:disabled="!Campaign"
title="New note"
aria-label="New note"
>
<img class="sidebar-action-icon" src="/icons/iconoir/regular/plus.svg" alt="" aria-hidden="true">
</button>
<button
class="sidebar-action"
type="button"
@click="fetchCampaignNotes"
:disabled="!Campaign || loadingNotes"
title="Refresh notes"
aria-label="Refresh notes"
>
<img class="sidebar-action-icon" src="/icons/iconoir/regular/refresh.svg" alt="" aria-hidden="true">
</button>
</div>
<div class="sidebar-header">
<div class="sidebar-copy">
<span class="sidebar-eyebrow">Campaign</span>
@@ -190,13 +171,13 @@ watch(Campaign, () => {
{{ notesError }}
</div>
<div v-else-if="notes.length === 0" class="sidebar-state">
<div v-else-if="TotalNotes.length === 0" class="sidebar-state">
No notes in this campaign yet.
</div>
<template v-else>
<button
v-for="note in notes"
v-for="note in TotalNotes"
:key="note.key"
type="button"
class="note-link"
@@ -217,7 +198,7 @@ watch(Campaign, () => {
display: flex;
}
.sidebar-actions {
.sidebar-tools {
width: 32px;
min-width: 32px;
padding: 8px 6px;
@@ -229,6 +210,11 @@ watch(Campaign, () => {
gap: 4px;
}
.sidebar-actions {
display: flex;
justify-content: center;
}
.sidebar-action {
width: 34px;
height: 34px;
@@ -242,10 +228,18 @@ watch(Campaign, () => {
align-items: center;
justify-content: center;
cursor: pointer;
&.active {
background-color: var(--color-selected);
}
}
.sidebar-action:hover {
background: var(--color-button-hover);
&.active {
background-color: var(--color-selected);
}
}
.sidebar-action:disabled {