frontend: add search and mailto
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
import Modal from '$lib/components/Modal.svelte';
|
import Modal from '$lib/components/Modal.svelte';
|
||||||
import UserEditForm from '$lib/components/UserEditForm.svelte';
|
import UserEditForm from '$lib/components/UserEditForm.svelte';
|
||||||
import SubscriptionEditForm from '$lib/components/SubscriptionEditForm.svelte';
|
import SubscriptionEditForm from '$lib/components/SubscriptionEditForm.svelte';
|
||||||
|
import InputField from '$lib/components/InputField.svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { applyAction, enhance } from '$app/forms';
|
import { applyAction, enhance } from '$app/forms';
|
||||||
@@ -25,6 +26,59 @@
|
|||||||
let selectedSubscription = null;
|
let selectedSubscription = null;
|
||||||
let showSubscriptionModal = false;
|
let showSubscriptionModal = false;
|
||||||
let showUserModal = 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.
|
* Opens the edit modal for the selected user.
|
||||||
@@ -50,7 +104,7 @@
|
|||||||
selectedUser = null;
|
selectedUser = null;
|
||||||
selectedSubscription = null;
|
selectedSubscription = null;
|
||||||
if (form) {
|
if (form) {
|
||||||
form.errors = undefined;
|
form.errors = [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,13 +171,32 @@
|
|||||||
{#if activeSection === 'users'}
|
{#if activeSection === 'users'}
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>{$t('users')}</h2>
|
<h2>{$t('users')}</h2>
|
||||||
<button class="btn primary" on:click={() => openEditUserModal(null)}>
|
<div class="title-container">
|
||||||
<i class="fas fa-plus"></i>
|
<InputField
|
||||||
{$t('add_new')}
|
name="search"
|
||||||
</button>
|
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>
|
||||||
<div class="accordion">
|
<div class="accordion">
|
||||||
{#each users as user}
|
{#each filteredUsers as user}
|
||||||
<details class="accordion-item">
|
<details class="accordion-item">
|
||||||
<summary class="accordion-header">
|
<summary class="accordion-header">
|
||||||
{user.first_name}
|
{user.first_name}
|
||||||
@@ -352,6 +425,18 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<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 {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -369,7 +454,6 @@
|
|||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
min-height: 600px;
|
|
||||||
background: var(--surface0);
|
background: var(--surface0);
|
||||||
border-right: 1px solid var(--surface1);
|
border-right: 1px solid var(--surface1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user