Skip to content
This repository has been archived by the owner on Jul 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #93 from AndresMorelos/subitems
Browse files Browse the repository at this point in the history
Subitems
  • Loading branch information
AndresMorelos authored Jun 19, 2022
2 parents 6192897 + 313cafd commit ea7c51a
Show file tree
Hide file tree
Showing 13 changed files with 609 additions and 394 deletions.
27 changes: 21 additions & 6 deletions app/actions/form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,35 @@ import * as ACTION_TYPES from '../constants/actions.jsx';
// Recipient
export const updateRecipient = createAction(
ACTION_TYPES.FORM_RECIPIENT_UPDATE,
data => data
(data) => data
);

// ItemsRow
export const addItem = createAction(ACTION_TYPES.FORM_ITEM_ADD);

export const removeItem = createAction(
ACTION_TYPES.FORM_ITEM_REMOVE,
itemID => itemID
(itemID) => itemID
);

export const updateItem = createAction(
ACTION_TYPES.FORM_ITEM_UPDATE,
itemData => itemData
(itemData) => itemData
);

export const addSubItem = createAction(
ACTION_TYPES.FORM_ITEM_ADD_SUBITEM,
(itemID) => itemID
);

export const removeSubItem = createAction(
ACTION_TYPES.FORM_ITEM_REMOVE_SUBITEM,
(parentItemId, itemID) => ({ id: itemID, parentItemId })
);

export const updateSubItem = createAction(
ACTION_TYPES.FORM_ITEM_UPDATE_SUBITEM,
(parentItemId, itemData) => ({ subItem: itemData, parentItemId })
);

export const moveRow = createAction(
Expand All @@ -30,12 +45,12 @@ export const addPaymentItem = createAction(ACTION_TYPES.FORM_PAYMENT_ITEM_ADD);

export const removePaymentItem = createAction(
ACTION_TYPES.FORM_PAYMENT_ITEM_REMOVE,
itemID => itemID
(itemID) => itemID
);

export const updatePaymentItem = createAction(
ACTION_TYPES.FORM_PAYMENT_ITEM_UPDATE,
itemData => itemData
(itemData) => itemData
);

export const movePaymentRow = createAction(
Expand Down Expand Up @@ -72,5 +87,5 @@ export const updateFieldData = createAction(

export const toggleField = createAction(
ACTION_TYPES.FORM_FIELD_TOGGLE,
field => field
(field) => field
);
172 changes: 117 additions & 55 deletions app/components/form/ItemRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@ import { compose } from 'recompose';
import styled from 'styled-components';
import _withDraggable from './hoc/_withDraggable';

// Custom Components
import SubItemsRow from './SubItemsRow';
import { Section } from '../shared/Section';

// Styles

const ItemsListDiv = styled.div`
position: relative;
margin-bottom: 10px;
`;

const ItemDiv = styled.div`
position: relative;
display: flex;
Expand Down Expand Up @@ -53,6 +62,13 @@ const ItemRemoveBtn = styled.a`
}
`;

const ItemAddSubiTemBtn = styled.a`
> i {
color: #00a8ff;
margin-right: 10px;
}
`;

// Component
export class ItemRow extends Component {
constructor(props) {
Expand All @@ -63,18 +79,22 @@ export class ItemRow extends Component {
this.updateSubtotal = this.updateSubtotal.bind(this);
this.uploadRowState = this.uploadRowState.bind(this);
this.removeRow = this.removeRow.bind(this);
this.addSubItem = this.addSubItem.bind(this);
this.removeSubItem = this.removeSubItem.bind(this);
this.updateSubItem = this.updateSubItem.bind(this);
}

UNSAFE_componentWillMount() {
const { id, description, quantity, price, subtotal } = this.props.item;
const index = this.props.index;
const { subItems, item, index } = this.props;
const { id, description, quantity, price, subtotal } = item;
this.setState({
id,
index,
description: description || '',
price: price || '',
quantity: quantity || '',
subtotal: subtotal || '',
subitems: subItems || [],
});
}

Expand Down Expand Up @@ -118,81 +138,123 @@ export class ItemRow extends Component {
}

uploadRowState() {
const { updateRow } = this.props;
updateRow(this.state);
const { updateRow, subItems } = this.props;
updateRow({
...this.state,
subitems: [...subItems, ...this.state.subitems],
});
}

removeRow() {
this.props.removeRow(this.state.id);
}

addSubItem() {
this.props.addSubItem(this.state.id);
}

removeSubItem(itemId) {
this.props.removeSubItem(this.state.id, itemId);
}

updateSubItem(item) {
this.props.updateSubItem(this.state.id, item);
}

render() {
const { t, actions, hasHandler } = this.props;
const { t, actions, hasHandler, subitemActions, subItems } = this.props;

const SubItemsRowsComponent = subItems.map((subItem, index) => (
<SubItemsRow
key={subItem.id}
item={subItem}
index={index}
t={t}
removeSubItem={this.removeSubItem}
updateSubItem={this.updateSubItem}
/>
));

return (
<ItemDiv>
{hasHandler && (
<div className="dragHandler">
<i className="ion-grid" />
<>
<ItemDiv>
{hasHandler && (
<div className="dragHandler">
<i className="ion-grid" />
</div>
)}
<div className="flex3">
<ItemDivInput
name="description"
type="text"
value={this.state.description}
onChange={this.handleTextInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:description')}
/>
</div>
)}
<div className="flex3">
<ItemDivInput
name="description"
type="text"
value={this.state.description}
onChange={this.handleTextInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:description')}
/>
</div>

<div className="flex1">
<ItemDivInput
name="price"
type="number"
step="0.01"
value={this.state.price}
onChange={this.handleNumberInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:price')}
/>
</div>

<div className="flex1">
<ItemDivInput
name="quantity"
type="number"
step="0.01"
value={this.state.quantity}
onChange={this.handleNumberInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:quantity')}
/>
</div>

{(actions || hasHandler) && (
<ItemActions>
{actions && (
<ItemRemoveBtn href="#" onClick={this.removeRow}>
<i className="ion-close-circled" />
</ItemRemoveBtn>
)}
</ItemActions>
)}
</ItemDiv>

<div className="flex1">
<ItemDivInput
name="price"
type="number"
step="0.01"
value={this.state.price}
onChange={this.handleNumberInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:price')}
/>
</div>

<div className="flex1">
<ItemDivInput
name="quantity"
type="number"
step="0.01"
value={this.state.quantity}
onChange={this.handleNumberInputChange}
onKeyDown={this.handleKeyDown}
placeholder={t('form:fields:items:quantity')}
/>
</div>

{(actions || hasHandler || subitemActions) && (
<ItemActions>
{subitemActions && (
<ItemAddSubiTemBtn href="#" onClick={this.addSubItem}>
<i className="ion-plus-circled" />
</ItemAddSubiTemBtn>
)}
{actions && (
<ItemRemoveBtn href="#" onClick={this.removeRow}>
<i className="ion-close-circled" />
</ItemRemoveBtn>
)}
</ItemActions>
)}
</ItemDiv>
<Section>
<ItemsListDiv>{SubItemsRowsComponent}</ItemsListDiv>
</Section>
</>
);
}
}

ItemRow.propTypes = {
actions: PropTypes.bool.isRequired,
subitemActions: PropTypes.bool.isRequired,
addItem: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
hasHandler: PropTypes.bool.isRequired,
item: PropTypes.object.isRequired,
subItems: PropTypes.array.isRequired,
index: PropTypes.number.isRequired,
removeRow: PropTypes.func.isRequired,
updateRow: PropTypes.func.isRequired,
addSubItem: PropTypes.func.isRequired,
removeSubItem: PropTypes.func.isRequired,
updateSubItem: PropTypes.func.isRequired,
};

export default compose(_withDraggable)(ItemRow);
27 changes: 18 additions & 9 deletions app/components/form/ItemsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,34 @@ export class ItemsList extends PureComponent {

render() {
// Bound Actions
const { addItem, removeItem, updateItem } = this.props.boundActionCreators;
const {
addItem,
removeItem,
updateItem,
addSubItem,
removeSubItem,
updateSubItem,
} = this.props.boundActionCreators;

// Item Rows
const { t, rows } = this.props;

const rowsComponent = rows.map((item, index) => (
<ItemRow
key={item.id}
item={item}
index={index}
t={t}
subItems={item.subitems || []}
hasHandler={rows.length > 1}
actions={index !== 0}
subitemActions
updateRow={updateItem}
removeRow={removeItem}
addItem={addItem}
addSubItem={addSubItem}
removeSubItem={removeSubItem}
updateSubItem={updateSubItem}
/>
));

Expand All @@ -94,11 +107,7 @@ export class ItemsList extends PureComponent {
<ItemsListHeader>
<label className="itemLabel">{t('form:fields:items:name')} *</label>
</ItemsListHeader>
<ItemsListDiv>
<TransitionList componentHeight={50}>
{rowsComponent}
</TransitionList>
</ItemsListDiv>
<ItemsListDiv>{rowsComponent}</ItemsListDiv>
<div className="itemsListActions">
<ItemsListActionsBtn primary onClick={addItem}>
{t('form:fields:items:add')}
Expand All @@ -115,12 +124,12 @@ ItemsList.propTypes = {
rows: PropTypes.arrayOf(PropTypes.object).isRequired,
};

const mapStateToProps = state => ({
const mapStateToProps = (state) => ({
formState: state.form, // Make drag & drop works
rows: getRows(state),
});

const mapDispatchToProps = dispatch => ({
const mapDispatchToProps = (dispatch) => ({
boundActionCreators: bindActionCreators(Actions, dispatch),
});

Expand Down
Loading

0 comments on commit ea7c51a

Please sign in to comment.