I am trying to recreate the search functionality of outlook. My entire data set is contained in the following interfaces:
export interface Folder{
id: string | null;
name: string;
folders: Folder[] | null;
emails: Email[]
}
export interface Email {
id : string;
conversation_id: string;
from: Contact;
to: Contact[];
cc: Contact[];
bcc: Contact[];
subject: string;
body: string;
body_preview: string;
has_attachments: boolean;
file_attachments: FileAttachment[];
received_date: Date
}
export interface Contact
{
email_address : number;
name : string | null;
}
export interface FileAttachment
{
id: string;
file_name: string;
content_type: string;
content_bytes: string;
}
As you can see it is a complex object with multiple layers and unknown depth as the folders can contain more folders and more emails. I have the following v-text-field which I will be using to search for strings in my nested object:
<v-text-field
v-model="search"
append-inner-icon="mdi-magnify"
label="Dynamic Search"
density="compact"
variant="outlined"
clearable
rounded
hide-details
single-line
flat
color="primaryDarken4"/>
I am looking to see an answer which shows how to maintain this structure of the objects but filters down the emails to those containing atleast 1 matching string in one of its properties.
This functions will help
function filterEmails(emailData: Email, searchTerm: string): boolean {
const searchTermLwCase = searchTerm.toLowerCase();
return (
emailData.subject.toLowerCase().includes(searchTermLwCase) ||
emailData.body.toLowerCase().includes(searchTermLwCase) ||
emailData.body_preview.toLowerCase().includes(searchTermLwCase) ||
emailData.from.name?.toLowerCase().includes(searchTermLwCase) ||
emailData.to.some(contact => contact.name?.toLowerCase().includes(searchTermLwCase)) ||
emailData.cc.some(contact => contact.name?.toLowerCase().includes(searchTermLwCase)) ||
emailData.bcc.some(contact => contact.name?.toLowerCase().includes(searchTermLwCase))
);
}
function searchForEmails(folder: Folder, searchTerm: string): Folder {
// emails filtered from current folder
const filteredEmails = folder.emails.filter(email => filterEmails(email, searchTerm));
// subfolder filter recursively
const filteredFolders = folder.folders ? folder.folders.map(subfolder => searchFolders(subfolder, searchTerm)).filter(subfolder => subfolder.emails.length > 0 || (subfolder.folders && subfolder.folders.length > 0)) : [];
return {
...folder,
emails: filteredEmails,
folders: filteredFolders
};
}