mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
feat: project table.
This commit is contained in:
@@ -15,7 +15,7 @@ const defaultInitialValues = {
|
|||||||
contact: '',
|
contact: '',
|
||||||
projectName: '',
|
projectName: '',
|
||||||
projectDeadline: moment(new Date()).format('YYYY-MM-DD'),
|
projectDeadline: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
projectState: true,
|
projectState: false,
|
||||||
projectCost: '',
|
projectCost: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
import { Classes, Position, FormGroup, ControlGroup } from '@blueprintjs/core';
|
import { Classes, Position, FormGroup, ControlGroup } from '@blueprintjs/core';
|
||||||
import { FastField } from 'formik';
|
import { FastField } from 'formik';
|
||||||
@@ -14,6 +15,7 @@ import {
|
|||||||
FMoneyInputGroup,
|
FMoneyInputGroup,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
|
FieldRequiredHint,
|
||||||
CustomerSelectField,
|
CustomerSelectField,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import {
|
import {
|
||||||
@@ -29,8 +31,12 @@ import { useProjectFormContext } from './ProjectFormProvider';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function ProjectFormFields() {
|
function ProjectFormFields() {
|
||||||
|
// project form dialog context.
|
||||||
const { customers } = useProjectFormContext();
|
const { customers } = useProjectFormContext();
|
||||||
|
|
||||||
|
// Formik context.
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={Classes.DIALOG_BODY}>
|
<div className={Classes.DIALOG_BODY}>
|
||||||
{/*------------ Contact -----------*/}
|
{/*------------ Contact -----------*/}
|
||||||
@@ -38,6 +44,7 @@ function ProjectFormFields() {
|
|||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.get('projects.dialog.contact')}
|
label={intl.get('projects.dialog.contact')}
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
>
|
>
|
||||||
@@ -93,7 +100,7 @@ function ProjectFormFields() {
|
|||||||
<ControlGroup>
|
<ControlGroup>
|
||||||
<InputPrependText text={'USD'} />
|
<InputPrependText text={'USD'} />
|
||||||
<FMoneyInputGroup
|
<FMoneyInputGroup
|
||||||
// disabled={true}
|
disabled={values.projectState}
|
||||||
name={'project_cost'}
|
name={'project_cost'}
|
||||||
allowDecimals={true}
|
allowDecimals={true}
|
||||||
allowNegativeValue={true}
|
allowNegativeValue={true}
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ const ProjectDialogContent = React.lazy(
|
|||||||
* Project form dialog.
|
* Project form dialog.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function ProjectFormDialog({ dialogName, payload: { projectId = null }, isOpen }) {
|
function ProjectFormDialog({
|
||||||
|
dialogName,
|
||||||
|
payload: { projectId = null },
|
||||||
|
isOpen,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<ProjectFormDialogRoot
|
<ProjectFormDialogRoot
|
||||||
name={dialogName}
|
name={dialogName}
|
||||||
@@ -35,16 +39,14 @@ const ProjectFormDialogRoot = styled(Dialog)`
|
|||||||
.bp3-dialog-body {
|
.bp3-dialog-body {
|
||||||
.bp3-form-group {
|
.bp3-form-group {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
margin-top: 15px;
|
|
||||||
|
|
||||||
label.bp3-label {
|
label.bp3-label {
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.bp3-dialog-footer {
|
.bp3-dialog-footer {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function ProjectsActionsBar({
|
|||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon="plus" />}
|
icon={<Icon icon="plus" />}
|
||||||
text={'New Project'}
|
text={<T id={'projects.label.new_project'} />}
|
||||||
onClick={handleNewProjectBtnClick}
|
onClick={handleNewProjectBtnClick}
|
||||||
/>
|
/>
|
||||||
{/* AdvancedFilterPopover */}
|
{/* AdvancedFilterPopover */}
|
||||||
|
|||||||
@@ -20,18 +20,22 @@ const projects = [
|
|||||||
name: 'Maroon Bronze',
|
name: 'Maroon Bronze',
|
||||||
deadline: '2022-06-08T22:00:00.000Z',
|
deadline: '2022-06-08T22:00:00.000Z',
|
||||||
display_name: 'Kyrie Rearden',
|
display_name: 'Kyrie Rearden',
|
||||||
cost_estimate: '4000',
|
cost_estimate: '40000',
|
||||||
task_amount: '1000',
|
task_amount: '10000',
|
||||||
is_in_process: true,
|
is_process: true,
|
||||||
|
is_closed: false,
|
||||||
|
is_draft: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: 'Project Sherwood',
|
name: 'Project Sherwood',
|
||||||
deadline: '2022-06-08T22:00:00.000Z',
|
deadline: '2022-06-08T22:00:00.000Z',
|
||||||
display_name: 'Ella-Grace Miller',
|
display_name: 'Ella-Grace Miller',
|
||||||
cost_estimate: '0',
|
cost_estimate: '700',
|
||||||
task_amount: '1000',
|
task_amount: '300',
|
||||||
is_in_process: true,
|
is_process: true,
|
||||||
|
is_closed: false,
|
||||||
|
is_draft: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -54,7 +58,8 @@ function ProjectsDataTable({
|
|||||||
// Handle cell click.
|
// Handle cell click.
|
||||||
const handleCellClick = ({ row: { original } }) => {
|
const handleCellClick = ({ row: { original } }) => {
|
||||||
return history.push(`/projects/${original?.id}/details`, {
|
return history.push(`/projects/${original?.id}/details`, {
|
||||||
name: original.name,
|
projectId: original.id,
|
||||||
|
projectName: original.name,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,7 +82,8 @@ function ProjectsDataTable({
|
|||||||
// Handle view detail project.
|
// Handle view detail project.
|
||||||
const handleViewDetailProject = (project) => {
|
const handleViewDetailProject = (project) => {
|
||||||
return history.push(`/projects/${project.id}/details`, {
|
return history.push(`/projects/${project.id}/details`, {
|
||||||
name: project.name,
|
projectId: project.id,
|
||||||
|
projectName: project.name,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,7 +125,7 @@ export default compose(
|
|||||||
const ProjectsTable = styled(DataTable)`
|
const ProjectsTable = styled(DataTable)`
|
||||||
.tbody {
|
.tbody {
|
||||||
.tr .td {
|
.tr .td {
|
||||||
padding: 0.8rem;
|
padding: 0.5rem 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar.td {
|
.avatar.td {
|
||||||
|
|||||||
@@ -19,30 +19,36 @@ import { safeCallback, firstLettersArgs, calculateStatus } from 'utils';
|
|||||||
export function ProjectStatus({ project }) {
|
export function ProjectStatus({ project }) {
|
||||||
return (
|
return (
|
||||||
<ProjectStatusRoot>
|
<ProjectStatusRoot>
|
||||||
{project.task_amount}
|
|
||||||
<ProjectProgressBar
|
<ProjectProgressBar
|
||||||
animate={false}
|
animate={false}
|
||||||
intent={Intent.NONE}
|
stripes={false}
|
||||||
|
// intent={Intent.PRIMARY}
|
||||||
value={calculateStatus(project.task_amount, project.cost_estimate)}
|
value={calculateStatus(project.task_amount, project.cost_estimate)}
|
||||||
/>
|
/>
|
||||||
|
<ProjectStatusTaskAmount>{project.task_amount}</ProjectStatusTaskAmount>
|
||||||
</ProjectStatusRoot>
|
</ProjectStatusRoot>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* project status accessor.
|
* status accessor.
|
||||||
*/
|
*/
|
||||||
export const ProjectStatusAccessor = (row) => {
|
export const StatusAccessor = (project) => {
|
||||||
return (
|
return (
|
||||||
<Choose>
|
<Choose>
|
||||||
<Choose.When condition={row.is_in_process}>
|
<Choose.When condition={project.is_process}>
|
||||||
<ProjectStatus project={row} />
|
<ProjectStatus project={project} />
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
<Choose.Otherwise>
|
<Choose.When condition={project.is_closed}>
|
||||||
|
<Tag minimal={true} intent={Intent.SUCCESS} round={true}>
|
||||||
|
<T id={'closed'} />
|
||||||
|
</Tag>
|
||||||
|
</Choose.When>
|
||||||
|
<Choose.When condition={project.is_draft}>
|
||||||
<Tag round={true} minimal={true}>
|
<Tag round={true} minimal={true}>
|
||||||
<T id={'draft'} />
|
<T id={'draft'} />
|
||||||
</Tag>
|
</Tag>
|
||||||
</Choose.Otherwise>
|
</Choose.When>
|
||||||
</Choose>
|
</Choose>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -126,19 +132,18 @@ export const useProjectsListColumns = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'name',
|
id: 'name',
|
||||||
Header: 'Project Name',
|
Header: '',
|
||||||
accessor: ProjectsAccessor,
|
accessor: ProjectsAccessor,
|
||||||
width: 240,
|
width: 200,
|
||||||
className: 'name',
|
className: 'name',
|
||||||
clickable: true,
|
clickable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status',
|
id: 'status',
|
||||||
Header: 'status',
|
Header: '',
|
||||||
accessor: ProjectStatusAccessor,
|
accessor: StatusAccessor,
|
||||||
width: 80,
|
width: 50,
|
||||||
className: 'status',
|
className: 'status',
|
||||||
clickable: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
@@ -150,10 +155,11 @@ const ProjectItemsWrap = styled.div``;
|
|||||||
const ProjectItemsHeader = styled.div`
|
const ProjectItemsHeader = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
line-height: 1.3rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProjectItemContactName = styled.div`
|
const ProjectItemContactName = styled.div`
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
`;
|
`;
|
||||||
const ProjectItemProjectName = styled.div``;
|
const ProjectItemProjectName = styled.div``;
|
||||||
@@ -162,23 +168,30 @@ const ProjectItemDescription = styled.div`
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
margin-top: 4px;
|
margin-top: 0.2rem;
|
||||||
|
line-height: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProjectStatusRoot = styled.div`
|
const ProjectStatusRoot = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: row-reverse;
|
justify-content: flex-end;
|
||||||
margin: 0 20px;
|
/* margin-right: 0.8rem; */
|
||||||
|
/* flex-direction: row-reverse; */
|
||||||
|
`;
|
||||||
|
const ProjectStatusTaskAmount = styled.div`
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
margin-left: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProjectProgressBar = styled(ProgressBar)`
|
const ProjectProgressBar = styled(ProgressBar)`
|
||||||
&.bp3-progress-bar {
|
&.bp3-progress-bar {
|
||||||
margin-right: 20px;
|
display: block;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
max-width: 130px;
|
max-width: 100px;
|
||||||
|
|
||||||
&,
|
&,
|
||||||
.bp3-progress-meter {
|
.bp3-progress-meter {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user