From 6363576c5e0ccfddc265794d7ffe499c3a0a62e3 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 25 Sep 2022 22:57:53 +0200
Subject: [PATCH] feat: project detail.
---
...ct.tsx => ProjectTaskChargeTypeSelect.tsx} | 2 +-
.../{TaskSelect.tsx => ProjectTaskSelect.tsx} | 7 +-
.../EstimatedExpenseFormFields.tsx | 4 +-
.../ProjectDetails/ProjectDetailProvider.tsx | 9 ++-
.../ProjectDetails/ProjectDetailsHeader.tsx | 75 +++++++++++++++++++
.../ProjectTasks/components.tsx | 39 +++++++---
.../ProjectDetails/ProjectTasks/index.tsx | 4 +-
.../ProjectTimeSheets/index.tsx | 4 +-
.../containers/ProjectDetails/utils.tsx | 30 ++++++++
.../ProjectExpenseFormFields.tsx | 4 +-
.../ProjectTimeEntryFormFields.tsx | 4 +-
.../containers/ProjectsLanding/components.tsx | 28 ++++---
src/lang/en/index.json | 20 ++++-
13 files changed, 192 insertions(+), 38 deletions(-)
rename src/containers/Projects/components/{ChangeTypesSelect.tsx => ProjectTaskChargeTypeSelect.tsx} (92%)
rename src/containers/Projects/components/{TaskSelect.tsx => ProjectTaskSelect.tsx} (93%)
create mode 100644 src/containers/Projects/containers/ProjectDetails/ProjectDetailsHeader.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/utils.tsx
diff --git a/src/containers/Projects/components/ChangeTypesSelect.tsx b/src/containers/Projects/components/ProjectTaskChargeTypeSelect.tsx
similarity index 92%
rename from src/containers/Projects/components/ChangeTypesSelect.tsx
rename to src/containers/Projects/components/ProjectTaskChargeTypeSelect.tsx
index 79335bd8e..db413bfe7 100644
--- a/src/containers/Projects/components/ChangeTypesSelect.tsx
+++ b/src/containers/Projects/components/ProjectTaskChargeTypeSelect.tsx
@@ -31,7 +31,7 @@ const chargeTypeSelectProps = {
* @param param0
* @returns
*/
-export function ChangeTypesSelect({ items, ...rest }) {
+export function ProjectTaskChargeTypeSelect({ items, ...rest }) {
return (
}
className={classNames('form-group--select-list', Classes.FILL)}
>
-
+
);
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectDetailsHeader.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectDetailsHeader.tsx
new file mode 100644
index 000000000..1039885c3
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectDetailsHeader.tsx
@@ -0,0 +1,75 @@
+// @ts-nocheck
+import React from 'react';
+import intl from 'react-intl-universal';
+import moment from 'moment';
+import styled from 'styled-components';
+import { Intent } from '@blueprintjs/core';
+import { FormatDate } from '@/components';
+import {
+ DetailFinancialCard,
+ DetailFinancialSection,
+ FinancialProgressBar,
+ FinancialCardText,
+} from './components';
+import { calculateStatus } from '@/utils';
+import { useCalculateProject } from './utils';
+
+import { useProjectDetailContext } from './ProjectDetailProvider';
+
+/**
+ * Project details header.
+ * @returns
+ */
+export function ProjectDetailHeader() {
+ const { project } = useProjectDetailContext();
+
+ const { percentageOfInvoice, percentageOfExpense } = useCalculateProject();
+
+ return (
+
+
+
+
+ {intl.get('project_details.label.of_project_estimate', {
+ value: percentageOfInvoice,
+ })}
+
+
+
+
+
+ {intl.get('project_details.label.of_project_estimate', {
+ value: percentageOfExpense,
+ })}
+
+
+
+
+
+ }
+ >
+ 4 days to go
+
+
+ );
+}
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectTasks/components.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectTasks/components.tsx
index 22ae3051b..ef5266013 100644
--- a/src/containers/Projects/containers/ProjectDetails/ProjectTasks/components.tsx
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectTasks/components.tsx
@@ -2,7 +2,7 @@
import React from 'react';
import intl from 'react-intl-universal';
import styled from 'styled-components';
-import { Icon } from '@/components';
+import { Icon, If, Choose, FormattedMessage as T } from '@/components';
import { Menu, MenuItem, Intent } from '@blueprintjs/core';
import { safeCallback } from '@/utils';
@@ -30,22 +30,39 @@ export function ActionsMenu({
);
}
-export function TaskAccessor(row) {
+/**
+ *
+ * @returns
+ */
+function TaskChrageType({ values: { charge_type, rate } }) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function TaskAccessor(task) {
return (
- {row.name}
+ {task.name}
- {row.charge_type === 'TIME'
- ? intl.get('project_task.rate', {
- rate: row.rate,
- })
- : row.charge_type}
+
+
- {row.estimate_minutes &&
- intl.get('project_task.estimate_minutes', {
- estimate_minutes: row.estimate_minutes,
+ {task.estimate_hours &&
+ intl.get('project_task.estimate_hours', {
+ estimate_hours: task.estimate_hours,
})}
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectTasks/index.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectTasks/index.tsx
index 75a572f2a..4389916c0 100644
--- a/src/containers/Projects/containers/ProjectDetails/ProjectTasks/index.tsx
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectTasks/index.tsx
@@ -2,14 +2,14 @@
import React from 'react';
import styled from 'styled-components';
-import { ProjectTasksHeader } from './ProjectTasksHeader';
+import { ProjectDetailHeader } from '../ProjectDetailsHeader';
import { ProjectTasksTable } from './ProjectTasksTable';
import { ProjectTaskProvider } from './ProjectTaskProvider';
export default function ProjectTasks() {
return (
-
+
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectTimeSheets/index.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectTimeSheets/index.tsx
index ccf2419d7..8570e58ce 100644
--- a/src/containers/Projects/containers/ProjectDetails/ProjectTimeSheets/index.tsx
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectTimeSheets/index.tsx
@@ -2,8 +2,8 @@
import React from 'react';
import styled from 'styled-components';
+import { ProjectDetailHeader } from '../ProjectDetailsHeader';
import { ProjectTimesheetsTable } from './ProjectTimesheetsTable';
-import { ProjectTimesheetsHeader } from './ProjectTimesheetsHeader';
import { ProjectTimesheetsProvider } from './ProjectTimesheetsProvider';
/**
@@ -13,7 +13,7 @@ import { ProjectTimesheetsProvider } from './ProjectTimesheetsProvider';
export default function ProjectTimeSheets() {
return (
-
+
diff --git a/src/containers/Projects/containers/ProjectDetails/utils.tsx b/src/containers/Projects/containers/ProjectDetails/utils.tsx
new file mode 100644
index 000000000..d569cf181
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/utils.tsx
@@ -0,0 +1,30 @@
+//@ts-nocheck
+
+import React from 'react';
+import moment from 'moment';
+import { subtract } from 'lodash';
+import { calculateStatus } from '@/utils';
+import { useProjectDetailContext } from './ProjectDetailProvider';
+
+function calculateProject(costEstiate, totalAmount) {
+ return (costEstiate / totalAmount) * 100;
+}
+
+export const useCalculateProject = () => {
+ const { project } = useProjectDetailContext();
+ const percentageOfInvoice = calculateProject(
+ project?.total_invoiced,
+ project?.cost_estimate,
+ );
+
+ const percentageOfExpense = calculateProject(
+ project?.total_expenses,
+ project?.cost_estimate,
+ );
+
+ return {
+ percentageOfInvoice,
+ percentageOfExpense,
+ };
+};
+
diff --git a/src/containers/Projects/containers/ProjectExpenseForm/ProjectExpenseFormFields.tsx b/src/containers/Projects/containers/ProjectExpenseForm/ProjectExpenseFormFields.tsx
index 996cd9e70..6284d181c 100644
--- a/src/containers/Projects/containers/ProjectExpenseForm/ProjectExpenseFormFields.tsx
+++ b/src/containers/Projects/containers/ProjectExpenseForm/ProjectExpenseFormFields.tsx
@@ -14,7 +14,7 @@ import {
import {
ExpenseSelect,
FInputGroupComponent,
- ChangeTypesSelect,
+ ProjectTaskChargeTypeSelect,
} from '../../components';
import ExpenseFormChargeFields from './ProjectExpenseFormChargeFields';
import { momentFormatter } from '@/utils';
@@ -100,7 +100,7 @@ export default function ProjectExpenseFormFields() {
label={}
className={classNames('form-group--select-list', Classes.FILL)}
>
- }
className={classNames('form-group--select-list', Classes.FILL)}
>
- {
-
- {row.status_formatted}
-
+
+
+ {row.status_formatted}
+
+
-
-
-
+
+
+
+
+
);
@@ -167,7 +171,7 @@ export const useProjectsListColumns = () => {
id: 'name',
Header: '',
accessor: ProjectsAccessor,
- width: 240,
+ width: 140,
className: 'name',
clickable: true,
},
@@ -232,7 +236,11 @@ const ProjectProgressBar = styled(ProgressBar)`
}
`;
-const StatusTag = styled(Tag)`
- min-width: 65px;
- text-align: center;
+const StatusTagWrap = styled.div`
+ display: flex;
+ justify-content: center;
+ .tag {
+ min-width: 65px;
+ text-align: center;
+ }
`;
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 65180dba4..26e1257f0 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -2083,8 +2083,10 @@
"project_task.dialog.edit_success_message": "The task has been edited successfully.",
"project_task.action.edit_task": "Edit Task",
"project_task.action.delete_task": "Delete Task",
- "project_task.rate": "{rate} /hour",
- "project_task.estimate_minutes": "• {estimate_minutes}h 0m estimated",
+ "project_task.rate": "{rate} / hour",
+ "project_task.fixed_price": "Fixed price",
+ "project_task.non_chargable": "Non-chargeable",
+ "project_task.estimate_hours": "• {estimate_hours}h 0m estimated",
"project_task.alert.delete_message": "The deleted task has been deleted successfully.",
"project_task.alert.once_delete_this_project": "Once you delete this task, you won't be able to restore it later. Are you sure you want to delete this task?",
"fixed_price": "Fixed price",
@@ -2095,7 +2097,7 @@
"project.schema.label.project_state": "Project state",
"project.schema.label.project_cost": "Project cost",
"project_task.schema.label.task_name": "Task name",
- "project_task.schema.label.task_house": "Task house",
+ "project_task.schema.label.estimate_hours": "Estimate hours",
"project_task.schema.label.charge_type": "Charge type",
"project_task.schema.label.rate": "Rate",
"project_task.schema.label.amount": "Amount",
@@ -2112,6 +2114,11 @@
"project_details.new_invoicing": "New Invoicing",
"project_details.new_expense": "New Expense",
"project_details.new_estimated_expense": "New Estimated Expense",
+ "project_details.label.project_estimate": "Project estimate",
+ "project_details.label.invoiced": "Invoiced",
+ "project_details.label.time_expenses": "Time & Expenses",
+ "project_details.label.to_be_invoiced": "To be invoiced",
+ "project_details.label.of_project_estimate": "{value}% of project estimate",
"timesheets.action.delete_timesheet": "Delete",
"timesheets.action.edit_timesheet": "Edit Timesheet",
"timesheets.column.date": "Date",
@@ -2215,5 +2222,10 @@
"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"
+ "project_billable_entries.dialog.bill": "Bill",
+ "project_billable_entries.dialog.add": "Add",
+ "project_billable_entries.dialog.show": "Show",
+ "project_billable_entries.alert.there_is_no_billable_entries": "There is no billable entries for that project.",
+ "project_billable_entries.billable_type": "Billable {value}",
+ "add_billable_entries": "Add Billable Entries"
}
\ No newline at end of file