frontend: add search and mailto

This commit is contained in:
Alex
2025-02-19 12:07:40 +01:00
parent cf037db080
commit 0e12286f15

View File

@@ -2,6 +2,7 @@
import Modal from '$lib/components/Modal.svelte';
import UserEditForm from '$lib/components/UserEditForm.svelte';
import SubscriptionEditForm from '$lib/components/SubscriptionEditForm.svelte';
import InputField from '$lib/components/InputField.svelte';
import { t } from 'svelte-i18n';
import { page } from '$app/stores';
import { applyAction, enhance } from '$app/forms';
@@ -25,6 +26,59 @@
let selectedSubscription = null;
let showSubscriptionModal = false;
let showUserModal = false;
let searchTerm = '';
$: filteredUsers = searchTerm ? getFilteredUsers() : users;
function handleMailButtonClick() {
const subject = 'Important Announcement';
const body = `Hello everyone,\n\nThis is an important message.`;
const bccEmails = filteredUsers
.map((/** @type{App.Locals['user']}*/ user) => user.email)
.join(',');
const encodedSubject = encodeURIComponent(subject);
const encodedBody = encodeURIComponent(body);
const mailtoLink = `mailto:?bcc=${bccEmails}&subject=${encodedSubject}&body=${encodedBody}`;
window.location.href = mailtoLink; // Open the mail client
}
/**
* returns a set of users depending on the entered search query
* @return {App.Locals['user'][]}*/
const getFilteredUsers = () => {
if (!searchTerm.trim()) return users;
const term = searchTerm.trim().toLowerCase();
return users.filter((/** @type{App.Locals['user']}*/ user) => {
const basicMatch = [
user.first_name?.toLowerCase(),
user.last_name?.toLowerCase(),
user.email?.toLowerCase(),
user.address?.toLowerCase(),
user.city?.toLowerCase(),
user.dateofbirth?.toLowerCase(),
user.phone?.toLowerCase(),
user.company?.toLowerCase(),
user.licence?.number?.toLowerCase()
].some((field) => field?.includes(term));
const subscriptionMatch = user.membership?.subscription_model?.name
?.toLowerCase()
.includes(term);
const licenceCategoryMatch = user.licence?.categories?.some((cat) =>
cat.category.toLowerCase().includes(term)
);
const addressMatch = [
user.address?.toLowerCase(),
user.zip_code?.toLowerCase(),
user.city?.toLowerCase()
].some((field) => field?.includes(term));
return basicMatch || subscriptionMatch || licenceCategoryMatch || addressMatch;
});
};
/**
* Opens the edit modal for the selected user.
@@ -50,7 +104,7 @@
selectedUser = null;
selectedSubscription = null;
if (form) {
form.errors = undefined;
form.errors = [];
}
};
@@ -117,13 +171,32 @@
{#if activeSection === 'users'}
<div class="section-header">
<h2>{$t('users')}</h2>
<button class="btn primary" on:click={() => openEditUserModal(null)}>
<i class="fas fa-plus"></i>
{$t('add_new')}
</button>
<div class="title-container">
<InputField
name="search"
placeholder={$t('placeholder.search')}
backgroundColor="--base"
/>
</div>
<!-- <input type="text" bind:value={searchTerm} placeholder={$t('placeholder.search')} /> -->
<div>
<button
class="btn primary"
aria-label="Mail Users"
on:click={() => handleMailButtonClick()}
>
<i class="fas fa-envelope"></i>
</button>
</div>
<div>
<button class="btn primary" on:click={() => openEditUserModal(null)}>
<i class="fas fa-plus"></i>
{$t('add_new')}
</button>
</div>
</div>
<div class="accordion">
{#each users as user}
{#each filteredUsers as user}
<details class="accordion-item">
<summary class="accordion-header">
{user.first_name}
@@ -352,6 +425,18 @@
{/if}
<style>
.title-container {
margin: 0 1rem;
flex-grow: 1;
max-width: 500px;
}
.section-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.container {
width: 100%;
height: 100%;
@@ -369,7 +454,6 @@
.sidebar {
width: 250px;
min-height: 600px;
background: var(--surface0);
border-right: 1px solid var(--surface1);
}