Skip to content

Commit

Permalink
feat: adding user multiselect + improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasz97 committed Sep 17, 2024
1 parent 23a9858 commit 74a33dc
Show file tree
Hide file tree
Showing 11 changed files with 248 additions and 153 deletions.
30 changes: 15 additions & 15 deletions src/components/report/ProductivitySection.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { component$, Signal, useSignal } from '@builder.io/qwik';
import { Project } from '@models/project';
import { RepotTab } from '@models/report';
import { ReportTab } from '@models/report';
import { Task } from '@models/task';
import { UserProfile } from '@models/user';
import { useProductivity } from 'src/hooks/report/useProductivity';
import { handlePrint } from 'src/utils/handlePrint';
import { Button } from '../Button';
Expand All @@ -10,32 +11,31 @@ import { ProductivityLegend } from './ProductivityLegend';
import { ProductivityTable } from './ProductivityTable';

interface ReportProps {
selectedCustomerSig: Signal<string[]>;
selectedProjectSig: Signal<Project[]>;
selectedTaskSig: Signal<Task[]>;
selectedNameSig: Signal<string>;
selectedTab: Signal<RepotTab>;
selectedCustomersSig: Signal<string[]>;
selectedProjectsSig: Signal<Project[]>;
selectedTasksSig: Signal<Task[]>;
selectedNamesSig: Signal<UserProfile[]>;
selectedTab: Signal<ReportTab>;
to: Signal<Date>;
from: Signal<Date>;
}

export const ProductivitySection = component$<ReportProps>(
({
to,
from,
selectedCustomerSig,
selectedProjectSig,
selectedTaskSig,
selectedNameSig,
selectedCustomersSig,
selectedProjectsSig,
selectedTasksSig,
selectedNamesSig,
selectedTab,
}) => {
const productivityTableRef = useSignal<HTMLElement>();

const { results: productivityResults } = useProductivity(
selectedCustomerSig,
selectedProjectSig,
selectedTaskSig,
selectedNameSig,
selectedCustomersSig,
selectedProjectsSig,
selectedTasksSig,
selectedNamesSig,
from,
to,
selectedTab
Expand Down
47 changes: 24 additions & 23 deletions src/components/report/ProjectsSection.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { component$, Signal, useSignal, useVisibleTask$ } from '@builder.io/qwik';
import { Project } from '@models/project';
import { RepotTab } from '@models/report';
import { ReportTab } from '@models/report';
import { Task } from '@models/task';
import { UserProfile } from '@models/user';
import { useReportProject } from 'src/hooks/report/useReportProject';
import { GroupByList } from './GropuByList';
import { ProjectReportDetails } from './ProjectReportDetails';
import { ProjectReportPreview } from './ProjectReportPreview';
import { ReportHeader } from './ReportHeader';

interface ReportProps {
selectedCustomerSig: Signal<string[]>;
selectedProjectSig: Signal<Project[]>;
selectedTaskSig: Signal<Task[]>;
selectedNameSig: Signal<string>;
selectedTab: Signal<RepotTab>;
selectedCustomersSig: Signal<string[]>;
selectedProjectsSig: Signal<Project[]>;
selectedTasksSig: Signal<Task[]>;
selectedNamesSig: Signal<UserProfile[]>;
selectedTab: Signal<ReportTab>;
to: Signal<Date>;
from: Signal<Date>;
}
Expand All @@ -22,10 +23,10 @@ export const ProjectsSection = component$<ReportProps>(
({
to,
from,
selectedCustomerSig,
selectedProjectSig,
selectedTaskSig,
selectedNameSig,
selectedCustomersSig,
selectedProjectsSig,
selectedTasksSig,
selectedNamesSig,
selectedTab,
}) => {
const projectReportDetailsRef = useSignal<HTMLElement>();
Expand All @@ -34,25 +35,25 @@ export const ProjectsSection = component$<ReportProps>(
const showProjectsDetails = useSignal(false);

const { results: projectResults } = useReportProject(
selectedCustomerSig,
selectedProjectSig,
selectedTaskSig,
selectedNameSig,
selectedCustomersSig,
selectedProjectsSig,
selectedTasksSig,
selectedNamesSig,
from,
to,
selectedTab
);

useVisibleTask$(({ track }) => {
track(() => selectedCustomerSig.value);
track(() => selectedProjectSig.value);
track(() => selectedTaskSig.value);
track(() => selectedNameSig.value);
track(() => selectedCustomersSig.value);
track(() => selectedProjectsSig.value);
track(() => selectedTasksSig.value);
track(() => selectedNamesSig.value);
showProjectsDetails.value =
selectedCustomerSig.value.length !== 0 ||
selectedProjectSig.value.length !== 0 ||
selectedTaskSig.value.length !== 0 ||
selectedNameSig.value !== '';
selectedCustomersSig.value.length !== 0 ||
selectedProjectsSig.value.length !== 0 ||
selectedTasksSig.value.length !== 0 ||
selectedNamesSig.value.length !== 0;
});

return (
Expand All @@ -61,7 +62,7 @@ export const ProjectsSection = component$<ReportProps>(
<div class='flex flex-col gap-1'>
<ReportHeader
printableComponent={projectReportDetailsRef}
customer={selectedCustomerSig}
customer={selectedCustomersSig}
data={projectResults.value}
/>

Expand Down
169 changes: 117 additions & 52 deletions src/components/report/ReportFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@ import { $, Signal, component$, sync$, useComputed$, useSignal } from '@builder.
import { Customer } from '@models/customer';
import { Project } from '@models/project';
import { Task } from '@models/task';
import { UserProfile } from '@models/user';
import { t } from 'src/locale/labels';
import { getAllTasks } from 'src/services/tasks';
import { getProjects } from 'src/services/projects';
import { getAllTasks, getTasks } from 'src/services/tasks';
import { getUserProfiles } from 'src/services/user';
import { UUID } from 'src/utils/uuid';
import { Button } from '../Button';
import { Input } from '../form/Input';
import { Multiselect } from '../form/Multiselect';

export const ReportFilters = component$<{
selectedCustomer: Signal<Customer[]>;
selectedProject: Signal<Project[]>;
selectedTask: Signal<Task[]>;
selectedName: Signal<string>;
}>(({ selectedCustomer, selectedProject, selectedTask, selectedName }) => {
selectedCustomers: Signal<Customer[]>;
selectedProjects: Signal<Project[]>;
selectedTasks: Signal<Task[]>;
selectedNames: Signal<UserProfile[]>;
}>(({ selectedCustomers, selectedProjects, selectedTasks, selectedNames }) => {
const getUniqueValues = sync$((arr: string[]): string[] => {
return [...new Set(arr)];
});

const _selectedProject = useSignal(selectedProject.value.map((project) => project.name));
const _selectedTask = useSignal(selectedTask.value.map((task) => task.name));
const _selectedProjects = useSignal(selectedProjects.value.map((project) => project.name));
const _selectedTasks = useSignal(selectedTasks.value.map((task) => task.name));
const _selectedUsers = useSignal(selectedNames.value.map((user) => user.name));

const taskProjectCustomerSig = useComputed$(async () => {
return await getAllTasks();
});

const usersSig = useComputed$(async () => {
return await getUserProfiles();
});

const _usersOptionsSig = useComputed$(async () => {
return usersSig.value.map((user) => user.name);
});

const customerOptionsSig = useComputed$(async () => {
return getUniqueValues(
taskProjectCustomerSig.value.map((taskProjectCustomer) => taskProjectCustomer.customer)
Expand All @@ -35,10 +46,10 @@ export const ReportFilters = component$<{
const _projectOptionsSig = useComputed$(async () => {
let customerProjects;

if (selectedCustomer.value.length !== 0) {
if (selectedCustomers.value.length !== 0) {
customerProjects = taskProjectCustomerSig.value.filter(
(element) =>
selectedCustomer.value.includes(element.customer) &&
selectedCustomers.value.includes(element.customer) &&
customerOptionsSig.value.includes(element.customer)
);
} else {
Expand All @@ -53,8 +64,8 @@ export const ReportFilters = component$<{
const _taskOptionsSig = useComputed$(async () => {
let taskProjects;

if (selectedProject.value.length !== 0) {
const projectNames = selectedProject.value.map((project) => project.name);
if (selectedProjects.value.length !== 0) {
const projectNames = selectedProjects.value.map((project) => project.name);
taskProjects = taskProjectCustomerSig.value.filter(
(element) =>
projectNames.includes(element.project) &&
Expand All @@ -67,44 +78,95 @@ export const ReportFilters = component$<{
return taskProjects.map((taskProjectCustomer) => taskProjectCustomer.task);
});

const onChangeTask = $(() => {
selectedTask.value = _selectedTask.value.map((task) => ({
name: task,
completed: false,
plannedHours: 0,
}));
const getProjectSig = $(async (project: string) => {
const customer = taskProjectCustomerSig.value.find(
(value) => value.project === project
)?.customer;
if (customer) {
const customerProjectList = await getProjects(customer);
return customerProjectList.find((element) => element.name === project);
}
});

const onChangeProject = $(() => {
selectedProject.value = _selectedProject.value.map((project) => ({
name: project,
type: '',
plannedHours: 0,
}));
const getTaskSig = $(async (task: string) => {
const project = taskProjectCustomerSig.value.find((value) => value.task === task)?.project;
const customer = taskProjectCustomerSig.value.find(
(value) => value.project === project
)?.customer;
if (customer && project) {
const projectTaskList = await getTasks(customer, project);
return projectTaskList.find((element) => element.name === task);
}
});

// TODO: use as base for task and project change
// const onChangeTask = $(() => {
// if (taskSig.value.length > 0) {
// const result = taskSig.value.find((task) => task.name === _selectedTask.value)!;

// if (result) {
// selectedTask.value = result;
// } else {
// selectedTask.value = {
// name: '',
// completed: false,
// plannedHours: 0,
// };
// }
// }
// });
const onChangeTask = $(async () => {
const selectedTaskNames = selectedTasks.value.map((task) => task.name);
const tasksToAdd = _selectedTasks.value.filter(
(taskName) => !selectedTaskNames.includes(taskName)
);

if (tasksToAdd.length > 0) {
for (const taskName of tasksToAdd) {
const task = await getTaskSig(taskName);
selectedTasks.value = [
...selectedTasks.value,
task ?? { name: taskName, completed: false, plannedHours: 0 },
];
}
} else {
const tasksToRemove = selectedTasks.value
.filter((task) => !_selectedTasks.value.includes(task.name))
.map((task) => task.name);

selectedTasks.value = selectedTasks.value.filter(
(task) => !tasksToRemove.includes(task.name)
);
}
});

const onChangeProject = $(async () => {
const selectedProjectNames = selectedProjects.value.map((proj) => proj.name);
const projectsToAdd = _selectedProjects.value.filter(
(projName) => !selectedProjectNames.includes(projName)
);

if (projectsToAdd.length > 0) {
for (const projName of projectsToAdd) {
const project = await getProjectSig(projName);
selectedProjects.value = [
...selectedProjects.value,
project ?? { name: projName, type: '', plannedHours: 0 },
];
}
} else {
const projectsToRemove = selectedProjects.value
.filter((proj) => !_selectedProjects.value.includes(proj.name))
.map((proj) => proj.name);

selectedProjects.value = selectedProjects.value.filter(
(proj) => !projectsToRemove.includes(proj.name)
);
}
});

const onChangeUser = $(() => {
selectedNames.value = _selectedUsers.value.map((user) => {
const value = usersSig.value.find((element) => element.name === user);
return (
value ?? {
name: user,
email: '',
id: '',
}
);
});
});

const clearFilters = $(() => {
selectedCustomer.value = [];
selectedProject.value = [];
_selectedTask.value = [];
selectedName.value = '';
selectedCustomers.value = [];
selectedProjects.value = [];
_selectedTasks.value = [];
selectedNames.value = [];
});

return (
Expand All @@ -113,7 +175,7 @@ export const ReportFilters = component$<{
id={UUID() + '-filter-customer'}
label={t('CUSTOMER_LABEL')}
placeholder={t('select_empty_label')}
value={selectedCustomer}
value={selectedCustomers}
options={customerOptionsSig}
allowSelectAll
/>
Expand All @@ -122,7 +184,7 @@ export const ReportFilters = component$<{
id={UUID() + '-filter-project'}
label={t('PROJECT_LABEL')}
placeholder={t('select_empty_label')}
value={_selectedProject}
value={_selectedProjects}
options={_projectOptionsSig}
onChange$={onChangeProject}
allowSelectAll
Expand All @@ -132,17 +194,20 @@ export const ReportFilters = component$<{
id={UUID() + '-filter-task'}
label={t('TASK_LABEL')}
placeholder={t('select_empty_label')}
value={_selectedTask}
value={_selectedTasks}
options={_taskOptionsSig}
onChange$={onChangeTask}
allowSelectAll
/>

<Input
id='filter-name'
<Multiselect
id={UUID() + '-filter-user'}
label={t('name_label')}
bindValue={selectedName}
placeholder={t('input_empty_label')}
placeholder={t('select_empty_label')}
value={_selectedUsers}
options={_usersOptionsSig}
onChange$={onChangeUser}
allowSelectAll
/>

<div class='flex items-end'>
Expand Down
Loading

0 comments on commit 74a33dc

Please sign in to comment.