Skip to content

Commit a166285

Browse files
committed
refactor: Simplify announcement filtering and improve archived announcements handling
1 parent e279814 commit a166285

File tree

1 file changed

+68
-68
lines changed

1 file changed

+68
-68
lines changed

src/routes/announcements/+page.svelte

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -22,52 +22,51 @@
2222
import ChevronDown from 'svelte-material-icons/ChevronDown.svelte';
2323
import Create from 'svelte-material-icons/Plus.svelte';
2424
25-
let searchParams: Readable<URLSearchParams>;
25+
let expanded = false;
2626
27-
if (building) searchParams = readable(new URLSearchParams());
28-
else searchParams = derived(page, ($page) => $page.url.searchParams);
27+
const searchParams: Readable<URLSearchParams> = building
28+
? readable(new URLSearchParams())
29+
: derived(page, ($page) => $page.url.searchParams);
2930
3031
let searchTerm = $searchParams.get('s') || '';
32+
let displayedTerm = '';
3133
3234
$: query = createQuery(queries.announcements());
3335
$: tagsQuery = createQuery(queries.announcementTags());
3436
$: selectedTags = $searchParams.getAll('tag');
3537
36-
let expanded = false;
37-
38-
function filterAnnouncements(
39-
announcements: Iterable<ResponseAnnouncement>,
40-
search: string,
41-
selectedTags: string[]
42-
): ResponseAnnouncement[] {
43-
const announcementFilter = createFilter(Array.from(announcements), {
44-
searcherOptions: {
45-
keys: ['title', 'content']
46-
},
47-
additionalFilter: (announcement: ResponseAnnouncement, tags: string[]): boolean => {
48-
return (
49-
tags.length === 0 ||
50-
tags.some((tag) => announcement.tags && announcement.tags.includes(tag))
51-
);
52-
}
53-
});
54-
55-
return announcementFilter(selectedTags, search);
56-
}
57-
58-
// Make sure we don't have to filter the announcements after every key press
59-
let displayedTerm = '';
6038
const update = () => {
6139
displayedTerm = searchTerm;
6240
6341
const url = new URL(window.location.href);
6442
url.pathname = '/announcements';
6543
66-
if (searchTerm) url.searchParams.set('s', searchTerm);
67-
else url.searchParams.delete('s');
44+
searchTerm ? url.searchParams.set('s', searchTerm) : url.searchParams.delete('s');
6845
};
6946
70-
onMount(update);
47+
const archivedAnnouncements = (announcements: ResponseAnnouncement[]) =>
48+
announcements.filter((a) => a.archived_at && moment(a.archived_at).isBefore(moment()));
49+
const activeAnnouncements = (announcements: ResponseAnnouncement[]) =>
50+
announcements.filter((a) => !a.archived_at || moment(a.archived_at).isAfter(moment()));
51+
52+
const filterAnnouncements = (
53+
announcements: ResponseAnnouncement[],
54+
search: string,
55+
tags: string[]
56+
): ResponseAnnouncement[] => {
57+
const announcementFilter = createFilter(announcements, {
58+
searcherOptions: { keys: ['title', 'content'] },
59+
60+
additionalFilter: (a: ResponseAnnouncement, tags: string[]) =>
61+
tags.length === 0 || tags.some((tag) => a.tags?.includes(tag))
62+
});
63+
64+
return announcementFilter(tags, search);
65+
};
66+
67+
onMount(() => {
68+
debounce(update)();
69+
});
7170
</script>
7271

7372
<div class="search">
@@ -92,60 +91,61 @@
9291
</Query>
9392

9493
<Query {query} let:data>
95-
<div class="cards">
96-
{#each filterAnnouncements(data.announcements, displayedTerm, selectedTags) as announcement}
97-
{#if !announcement.archived_at || moment(announcement.archived_at).isAfter(moment())}
98-
{#key selectedTags || displayedTerm}
99-
<div in:fly={{ y: 10, easing: quintOut, duration: 750 }}>
100-
<AnnouncementCard {announcement} />
101-
</div>
102-
{/key}
103-
{/if}
104-
{/each}
105-
</div>
106-
107-
<div
108-
role="button"
109-
class="expand-archived"
110-
aria-expanded={expanded}
111-
class:closed={!expanded}
112-
on:click={() => (expanded = !expanded)}
113-
on:keypress={() => (expanded = !expanded)}
114-
tabindex="0"
115-
>
116-
<h4>Archived announcements</h4>
117-
118-
<div id="arrow" style:transform={expanded ? 'rotate(0deg)' : 'rotate(-180deg)'}>
119-
<ChevronDown size="24px" color="var(--surface-six)" />
94+
{#if activeAnnouncements(filterAnnouncements(data.announcements, displayedTerm, selectedTags)).length}
95+
<div class="cards">
96+
{#each activeAnnouncements(filterAnnouncements(data.announcements, displayedTerm, selectedTags)) as announcement}
97+
<div in:fly={{ y: 10, easing: quintOut, duration: 750 }}>
98+
<AnnouncementCard {announcement} />
99+
</div>
100+
{/each}
120101
</div>
121-
</div>
102+
{/if}
122103

123-
{#if expanded}
104+
{#if archivedAnnouncements(filterAnnouncements(data.announcements, displayedTerm, selectedTags)).length}
124105
<div
125-
class="cards"
126-
in:slide={{ easing: quintIn, duration: 250 }}
127-
out:slide={{ easing: quintOut, duration: 250 }}
106+
role="button"
107+
class="expand-archived"
108+
aria-expanded={expanded}
109+
on:click={() => (expanded = !expanded)}
110+
on:keypress={() => (expanded = !expanded)}
111+
tabindex="0"
128112
>
129-
{#each filterAnnouncements(data.announcements, displayedTerm, selectedTags) as announcement}
130-
{#if announcement.archived_at && moment(announcement.archived_at).isBefore(moment())}
131-
{#key selectedTags || displayedTerm}
132-
<AnnouncementCard {announcement} />
133-
{/key}
134-
{/if}
135-
{/each}
113+
<h4>Archived announcements</h4>
114+
115+
<div id="arrow" style:transform={expanded ? 'rotate(-180deg)' : 'rotate(0deg)'}>
116+
<ChevronDown size="24px" color="var(--surface-six)" />
117+
</div>
136118
</div>
119+
120+
{#if expanded}
121+
<div
122+
class="cards"
123+
in:slide={{ easing: quintIn, duration: 250 }}
124+
out:slide={{ easing: quintOut, duration: 250 }}
125+
>
126+
{#each archivedAnnouncements(filterAnnouncements(data.announcements, displayedTerm, selectedTags)) as announcement}
127+
<AnnouncementCard {announcement} />
128+
{/each}
129+
</div>
130+
{/if}
137131
{/if}
138132
</Query>
139133
</main>
140134

141135
<style lang="scss">
136+
main {
137+
display: flex;
138+
flex-direction: column;
139+
gap: 1rem;
140+
}
141+
142142
.expand-archived {
143143
display: flex;
144144
align-items: center;
145145
justify-content: space-between;
146146
cursor: pointer;
147147
user-select: none;
148-
padding: 0rem 0.25rem;
148+
padding-inline: 0.25rem;
149149
150150
#arrow {
151151
height: 1.5rem;

0 commit comments

Comments
 (0)