diff --git a/src/containers/Projects/components/ProjectBillableTypeSuggestField.tsx b/src/containers/Projects/components/ProjectBillableTypeSuggestField.tsx
new file mode 100644
index 000000000..12996c5b8
--- /dev/null
+++ b/src/containers/Projects/components/ProjectBillableTypeSuggestField.tsx
@@ -0,0 +1,132 @@
+// @ts-nocheck
+import React from 'react';
+import intl from 'react-intl-universal';
+import { Menu, MenuItem } from '@blueprintjs/core';
+import { Suggest } from '@blueprintjs/select';
+import { FormattedMessage as T } from '@/components';
+
+import classNames from 'classnames';
+import { CLASSES } from '@/constants/classes';
+
+/**
+ * @param {*} billableType
+ * @param {*} param1
+ * @returns {JSX.Element}
+ */
+const billableTypeItemRenderer = (
+ billableType,
+ { handleClick, modifiers, query },
+) => {
+ return (
+
+ );
+};
+
+/**
+ *
+ * @param {*} query
+ * @param {*} billableType
+ * @param {*} _index
+ * @param {*} exactMatch
+ * @returns
+ */
+const billableTypeItemPredicate = (query, billableType, _index, exactMatch) => {
+ const normalizedTitle = billableType.name.toLowerCase();
+ const normalizedQuery = query.toLowerCase();
+
+ if (exactMatch) {
+ return normalizedTitle === normalizedQuery;
+ } else {
+ return (
+ `${billableType.name}. ${normalizedTitle}`.indexOf(normalizedQuery) >= 0
+ );
+ }
+};
+
+/**
+ *
+ * @param inputValue
+ * @returns
+ */
+const billableTypeInputValueRenderer = (inputValue) => {
+ if (inputValue) {
+ return inputValue.name.toString();
+ }
+ return '';
+};
+
+/**
+ * Project billable suggest field.
+ * @param
+ */
+export function ProjectBillableSuggestField({
+ billableType,
+ initialBillableTypeId,
+ selectedBillableTypeId,
+
+ defautlSelectText = 'Placeholder Type...',
+ onBillableTypeSelected,
+ popoverFill = false,
+
+ ...suggestProps
+}) {
+ const initialBillableType = React.useMemo(
+ () => billableType.find((b) => b.id === initialBillableTypeId),
+ [initialBillableTypeId, billableType],
+ );
+
+ const [selectedBillableType, setSelectedBillableType] = React.useState(
+ initialBillableType || null,
+ );
+
+ React.useEffect(() => {
+ if (typeof selectedBillableTypeId !== 'undefined') {
+ const billableType = selectedBillableTypeId
+ ? billableType.find((a) => a.id === selectedBillableTypeId)
+ : null;
+ setSelectedBillableType(billableType);
+ }
+ }, [selectedBillableTypeId, billableType, setSelectedBillableType]);
+
+ /**
+ *
+ * @param {*} billableType
+ * @returns
+ */
+ const billableTypetemSelect = React.useCallback(
+ (billableType) => {
+ if (billableType.id) {
+ setSelectedBillableType({ ...billableType });
+ onBillableTypeSelected && onBillableTypeSelected(billableType);
+ }
+ },
+ [setSelectedBillableType, onBillableTypeSelected],
+ );
+
+ const billableTypeSelectProps = {
+ itemRenderer: billableTypeItemRenderer,
+ itemPredicate: billableTypeItemPredicate,
+ inputValueRenderer: billableTypeInputValueRenderer,
+ };
+ return (
+
+ );
+}
diff --git a/src/containers/Projects/components/ProjectSuggestField.tsx b/src/containers/Projects/components/ProjectSuggestField.tsx
index 56cd61df0..216606a5f 100644
--- a/src/containers/Projects/components/ProjectSuggestField.tsx
+++ b/src/containers/Projects/components/ProjectSuggestField.tsx
@@ -48,15 +48,13 @@ export function ProjectSuggestField({
*/
const projectsItemRenderer = (project, { handleClick, modifiers, query }) => {
return (
-
- }
- disabled={modifiers.disabled}
- key={project.id}
- text={project.name}
- onClick={handleClick}
- />
-
+ }
+ disabled={modifiers.disabled}
+ key={project.id}
+ text={project.name}
+ onClick={handleClick}
+ />
);
};
@@ -133,20 +131,14 @@ const AvatarSelect = ({ text }) => {
return {firstLettersArgs(text?.name)};
};
-const MenuContent = styled(Menu)`
- .bp3-menu {
- margin: 5px;
- }
-`;
-
const AvaterContent = styled.div`
display: inline-block;
background: #adbcc9;
text-align: center;
font-weight: 400;
color: #fff;
- height: 25px;
- width: 25px;
- line-height: 25px;
+ height: 22px;
+ width: 22px;
+ line-height: 22px;
font-size: 12px;
`;
diff --git a/src/containers/Projects/components/index.ts b/src/containers/Projects/components/index.ts
index b27dbd340..b0dd663ed 100644
--- a/src/containers/Projects/components/index.ts
+++ b/src/containers/Projects/components/index.ts
@@ -5,4 +5,5 @@ export * from './TaskSelect';
export * from './ProjectsSelect';
export * from './ProjectMultiSelect'
export * from './FInputGroupComponent';
-export * from './ProjectSuggestField'
\ No newline at end of file
+export * from './ProjectSuggestField'
+export * from './ProjectBillableTypeSuggestField'
\ No newline at end of file
diff --git a/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormFields.tsx b/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormFields.tsx
index 636ea8966..b0f771eba 100644
--- a/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormFields.tsx
+++ b/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormFields.tsx
@@ -9,6 +9,8 @@ import {
FieldRequiredHint,
FormattedMessage as T,
} from '@/components';
+import { ProjectBillableSuggestField } from '../../components';
+import { billableTypeOption } from '../common';
import { ProjectRowDivider, ProjectEntiresBox } from './components';
import { useProjectBillableEntriesFormContext } from './ProjectBillableEntriesFormProvider';
@@ -20,8 +22,6 @@ export default function ProjectBillableEntriesFormFields() {
// Formik context.
const { values } = useFormikContext();
- const { billableEntries } = useProjectBillableEntriesFormContext();
-
return (
{/*------------ Filter by Date -----------*/}
@@ -37,14 +37,14 @@ export default function ProjectBillableEntriesFormFields() {
{/*------------ Filter by Type -----------*/}
}
labelInfo={
}
>
-
+
-
+
);
}
diff --git a/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormProvider.tsx b/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormProvider.tsx
index 589bd3f89..4f9aa522f 100644
--- a/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormProvider.tsx
+++ b/src/containers/Projects/containers/ProjectBillableEntriesFormDialog/ProjectBillableEntriesFormProvider.tsx
@@ -1,7 +1,6 @@
// @ts-nocheck
import React from 'react';
-import { useProjectBillableEntries } from '../../hooks';
import { DialogContent } from '@/components';
const ProjectBillableEntriesFormContext = React.createContext();
@@ -16,31 +15,14 @@ function ProjectBillableEntriesFormProvider({
projectId,
...props
}) {
- // Handle fetch project billable entries.
- const {
- data: { billableEntries },
- isLoading: isProjectBillableEntriesLoading,
- } = useProjectBillableEntries(
- projectId,
- {
- billable_type: 'expense',
- to_date: '',
- },
- {
- enabled: !!projectId,
- keepPreviousData: true,
- },
- );
-
//state provider.
const provider = {
dialogName,
projectId,
- billableEntries,
};
return (
-
+
);
diff --git a/src/containers/Projects/containers/common/modalChargeOptions.ts b/src/containers/Projects/containers/common/modalChargeOptions.ts
index e1dd36b5a..f4462b3c0 100644
--- a/src/containers/Projects/containers/common/modalChargeOptions.ts
+++ b/src/containers/Projects/containers/common/modalChargeOptions.ts
@@ -4,7 +4,10 @@ import intl from 'react-intl-universal';
export const taskChargeOptions = [
{ name: intl.get('project_task.dialog.hourly_rate'), value: 'TIME' },
{ name: intl.get('project_task.dialog.fixed_price'), value: 'FIXED' },
- { name: intl.get('project_task.dialog.non_chargeable'), value: 'NON_CHARGABLE' },
+ {
+ name: intl.get('project_task.dialog.non_chargeable'),
+ value: 'NON_CHARGABLE',
+ },
];
export const expenseChargeOption = [
@@ -16,3 +19,12 @@ export const expenseChargeOption = [
{ name: intl.get('expenses.dialog.custom_pirce'), value: 'custom_pirce' },
{ name: intl.get('expenses.dialog.non_chargeable'), value: 'non_chargeable' },
];
+
+export const billableTypeOption = [
+ { name: intl.get('project_billable_entries.dialog.task'), value: 'Task' },
+ { name: intl.get('project_billable_entries.dialog.bill'), value: 'Bill' },
+ {
+ name: intl.get('project_billable_entries.dialog.expense'),
+ value: 'Expense',
+ },
+];
diff --git a/src/containers/Projects/hooks/projectBillableEntries.tsx b/src/containers/Projects/hooks/projectBillableEntries.tsx
index 72f63a90f..a2da2b86f 100644
--- a/src/containers/Projects/hooks/projectBillableEntries.tsx
+++ b/src/containers/Projects/hooks/projectBillableEntries.tsx
@@ -12,7 +12,7 @@ import t from './type';
*/
export function useProjectBillableEntries(projectId, query, props) {
return useRequestQuery(
- [t.PROJECT_BILLABLE_ENTRIES, projectId],
+ [t.PROJECT_BILLABLE_ENTRIES, projectId, query],
{
method: 'get',
url: `projects/${projectId}/billable/entries`,
@@ -20,9 +20,7 @@ export function useProjectBillableEntries(projectId, query, props) {
},
{
select: (res) => res.data.billable_entries,
- defaultData: {
- billableEntries: [],
- },
+ defaultData: {},
...props,
},
);
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 64b3b0c71..65180dba4 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -2212,5 +2212,8 @@
"project_invoicing.dialog.bill_to": "Bill To",
"project_billable_entries.dialog.label": "Add Project Entries",
"project_billable_entries.dialog.filter_by_date": "Filter by Date",
- "project_billable_entries.dialog.filter_by_type":"Filter by Type"
+ "project_billable_entries.dialog.filter_by_type": "Filter by Type",
+ "project_billable_entries.dialog.expense": "Expense",
+ "project_billable_entries.dialog.task": "Task",
+ "project_billable_entries.dialog.bill": "Bill"
}
\ No newline at end of file