Skip to content

Commit

Permalink
Merge branch '6_Accounts_Merchants_List_Search_Get_Add' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
zlkca committed May 1, 2020
2 parents 16c598d + 7685931 commit 1795939
Show file tree
Hide file tree
Showing 12 changed files with 540 additions and 18,611 deletions.
18,368 changes: 0 additions & 18,368 deletions package-lock.json

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -11,7 +11,7 @@
"classnames": "2.2.6",
"history": "4.9.0",
"i18next": "^19.4.1",
"moment": "^2.24.0",
"moment": "2.24.0",
"moment-timezone": "^0.5.28",
"perfect-scrollbar": "1.4.0",
"prop-types": "15.7.2",
Expand Down
10 changes: 4 additions & 6 deletions src/assets/css/duocun.css
@@ -1,10 +1,8 @@

/** Common */
/** textarea */
.dc-full-textarea {
width: 100%;
}
/** table */
table.dc-table {
min-width: 750
}
}
.dc-full, .dc-full-select, .dc-full-textarea {
width: 100%
}
21 changes: 11 additions & 10 deletions src/services/api/ApiAccountService.js
@@ -1,18 +1,16 @@
import ApiService from "services/api/ApiService";
import { buildPaginationQuery } from "helper/index";
export default {
getAccountList: (page, pageSize, search = "", sort = []) => {
getAccountList: (page, pageSize, {username, type}, sort = []) => {
let query = {};
if (!search) {
query.query = buildPaginationQuery(page, pageSize, {}, [], sort);
} else {
const condition = {
username: {
$regex: search,
},
};
query.query = buildPaginationQuery(page, pageSize, condition, [], sort);
let conditions = {};
if (username) {
conditions.username = { $regex: username };
}
if (type) {
conditions.type = type;
}
query.query = buildPaginationQuery(page, pageSize, conditions, [], sort);
return ApiService.v2().get("accounts", query);
},
getAccountAllKeyword: (keyword = "") => {
Expand Down Expand Up @@ -41,4 +39,7 @@ export default {
);
return ApiService.v2().get("accounts", query);
},
createAccount: (accountData = {}) => {
return ApiService.v2().post("accounts", accountData);
},
};
5 changes: 4 additions & 1 deletion src/services/api/ApiMerchantService.js
Expand Up @@ -14,5 +14,8 @@ export default {
query.query = buildPaginationQuery(page, pageSize, condition, [], sort);
}
return ApiService.v2().get("merchants", query);
}
},
createMerchant: (merchantData = {}) => {
return ApiService.v2().post("merchants", merchantData);
},
};
237 changes: 233 additions & 4 deletions src/views/Accounts/AccountsForm.js
@@ -1,8 +1,237 @@
import React from "react";
const AccountForm = () => {
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

import { Save as SaveIcon, FormatListBulleted as FormatListBulletedIcon } from "@material-ui/icons";
import { TextField, Button, Checkbox,
Select, MenuItem, InputLabel, FormControl, FormControlLabel } from "@material-ui/core";
import { Alert } from "@material-ui/lab"

import GridContainer from "components/Grid/GridContainer.js";
import GridItem from "components/Grid/GridItem.js";
import Card from "components/Card/Card.js";
import CardHeader from "components/Card/CardHeader.js";
import CardBody from "components/Card/CardBody.js";
import CardFooter from "components/Card/CardFooter.js";

import EditSkeleton from "../Common/EditSkeleton";
import ApiAccountService from "services/api/ApiAccountService";

const defaultAccountsModelState = {
_id: 'new',
username: "",
imageurl: "",
realm: "",
sex: "",
openId: "",
type: "merchant",
balance: 0,
phone: "",
created: "",
verificationCode: "",
verified: true,
attributes: []
}
const AccountsForm = ({}) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [processing, setProcessing] = useState(false);

// for model
const [model, setModel] = useState(defaultAccountsModelState);
const [alert, setAlert] = useState({ message: "", severity: "info" });

const _ATTRIBUTES = {
I: "INDOOR",
G: "GARDENING",
R: "ROOFING",
O: "OFFICE",
P: "PLAZA",
H: "HOUSE",
C: "CONDO",
}

//////////////////// For data fetch
const getAccountData = () => {

}

/////////////////// For render and events

const _renderUserInfo = ()=> {
return <React.Fragment>
<GridItem xs={12}>
<h5>{t("Basic Information")}</h5>
</GridItem>
<GridItem xs={12} lg={12} >
<FormControl className="dc-full-select">
<InputLabel id="merchant-type-label">Type</InputLabel>
<Select required labelId="merchant-type-label" id="account-type"
value={model.type} onChange={ e => setModel({...model, type: e.target.value})} >
<MenuItem value={'merchant'}>Merchant</MenuItem>
<MenuItem value={'driver'}>Driver</MenuItem>
<MenuItem value={'client'}>Client</MenuItem>
<MenuItem value={'system'}>System</MenuItem>
<MenuItem value={'freight'}>Freight</MenuItem>
</Select>
</FormControl>
</GridItem>
<GridItem xs={12} md={6} lg={6}>
<TextField id="account-username" label={`${t("Username")}`}
required className="dc-full" value={model.username}
onChange={e => { setModel({ ...model, username: e.target.value }); }}
/>
</GridItem>
<GridItem xs={12} md={6} lg={6}>
<TextField id="account-imageurl" label={`${t("ImageUrl")}`}
disabled className="dc-full" value={model.imageurl}
onChange={e => { setModel({ ...model, imageurl: e.target.value }); }}
/>
</GridItem>
<GridItem xs={12} md={6} lg={6}>
<TextField id="account-realm" label={`${t("Realm")}`}
disabled className="dc-full" value={model.realm}
onChange={e => { setModel({ ...model, realm: e.target.value }); }}
/>
</GridItem>
<GridItem xs={12} md={6} lg={6}>
<TextField id="account-sex" label={`${t("Sex")}`}
disabled className="dc-full" value={model.sex}
onChange={e => { setModel({ ...model, sex: e.target.value }); }}
/>
</GridItem>
<GridItem xs={12} md={6} lg={6}>
<TextField id="account-phone" label={`${t("Phone")}`}
disabled className="dc-full" value={model.phone}
onChange={e => { setModel({ ...model, phone: e.target.value }); }}
/>
</GridItem>
</React.Fragment>
}
const _attributeClick = (e, _key) => {
const attr = model.attributes || [];
if (e.target.checked) {
if (attr.indexOf(_key) < 0 ) {
attr.push(_key);
}
} else {
const index = attr.indexOf(_key);
if (index >= 0 ) {
attr.splice(index, 1);
}
}
setModel({...model, attributes: attr});
}
const _renderAttributes = () => {
return <React.Fragment>
<GridItem xs={12}>
<h5>{t("Attributes")}</h5>
</GridItem>
<GridItem xs={12} lg={12} >
<GridContainer>
{
Object.keys(_ATTRIBUTES).map( _key => {
return <GridItem xs={6} lg={6} >
<FormControlLabel
control={<Checkbox checked={model.attributes.indexOf(_key)>=0}
onChange={(e) => _attributeClick(e, _key)} color="primary" />}
label={_ATTRIBUTES[_key]||_key}
labelPlacement="end"
/>
</GridItem>
})
}
</GridContainer>
</GridItem>
</React.Fragment>
}

const renderRight = () => {
return <GridContainer>
{_renderAttributes()}
</GridContainer>
}
const renderLeft = () => {
return <GridContainer>
{_renderUserInfo()}
</GridContainer>
}
const removeAlert = () => {
setAlert({
message: "",
severity: "info"
});
};


////////////////////////////////////
// For submit
const saveModel = () => {
setProcessing(true);
ApiAccountService.createAccount(model).then(
({ data }) => {
setProcessing(false);
if ( data.code === "success" ) {
// success
setAlert({
message: "Created success!",
severity: "success"
});
} else {
// failure
setAlert({
message: data.data,
severity: "error"
});
}
}
);
}

return (
<div>Account Form</div>
<GridContainer>
<GridItem xs={12} lg={12}>
<Card>
<CardHeader color="primary">
{loading && <h4>{t("Merchants")}</h4>}
{!loading && (
<h4>
{model._id && model._id !== "new"
? t("Edit Account") + ": " + model.name
: t("Add Account")}
</h4>
)}
</CardHeader>
<CardBody>
{loading && <EditSkeleton />}
{!!alert.message && (
<Alert severity={alert.severity} onClose={removeAlert}>
{alert.message}
</Alert>
)}
{!loading && <GridContainer>
<GridItem xs={12} md={6} lg={6}>{renderLeft()}</GridItem>
<GridItem xs={12} md={6} lg={6}>{renderRight()} </GridItem>
</GridContainer>}
</CardBody>
<CardFooter direction="row-reverse">
<GridContainer>
<GridItem xs={12} >
<Button color="primary" variant="contained"
disabled={loading || processing || !model.username || !model.type }
onClick={saveModel} >
<SaveIcon /> {t("Save")}
</Button>
&nbsp;&nbsp;&nbsp;&nbsp;
<Button variant="contained" href="../Merchants">
<FormatListBulletedIcon /> {t("Back")}
</Button>
</GridItem>
</GridContainer>
</CardFooter>
</Card>
</GridItem>
</GridContainer>
);
};

export default AccountForm;
export default AccountsForm;
19 changes: 12 additions & 7 deletions src/views/Accounts/AccountsTable.js
@@ -1,8 +1,9 @@
import React, { useState, useEffect } from "react";
import React from "react";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";

import { Avatar, Chip, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TableSortLabel } from "@material-ui/core";
import { Avatar, Chip, Table, TableBody, TableCell, TableContainer,
TableHead, TableRow, TableSortLabel, Switch } from "@material-ui/core";
import LocalMallIcon from "@material-ui/icons/LocalMall";

import TableBodySkeleton from "components/Table/TableBodySkeleton";
Expand Down Expand Up @@ -41,7 +42,7 @@ export default function AccountsTable({ accounts, rowsPerPage, toggleSort, sort,
return (
<React.Fragment>
{rows.map((row, idx) => (
<TableRow key={idx}>
<TableRow key={`${row._id}_${idx}`}>
<TableCell>{page * rowsPerPage + idx + 1}</TableCell>
<TableCell>
<Avatar
Expand All @@ -56,14 +57,18 @@ export default function AccountsTable({ accounts, rowsPerPage, toggleSort, sort,
<TableCell>{row.type}</TableCell>
<TableCell>{row.phone}</TableCell>
<TableCell>{row.balance}</TableCell>
<TableCell>{row.email}</TableCell>
<TableCell>
<Switch checked={row.verified} name="checkedA" color="primary"
inputProps={{ 'aria-label': 'primary checkbox' }}
/>
</TableCell>
<TableCell>
{row.roles &&
row.roles
.map(item => ROLE_MAPPING[item] || item)
.map(item => (
// eslint-disable-next-line react/jsx-key
<React.Fragment>
<React.Fragment key={`${item}`}>
<Chip variant="outlined" size="small" label={item} />
<br />
</React.Fragment>
Expand All @@ -75,7 +80,7 @@ export default function AccountsTable({ accounts, rowsPerPage, toggleSort, sort,
.map(item => ATTRIBUTES_MAPPING[item] || item)
.map(item => (
// eslint-disable-next-line react/jsx-key
<React.Fragment>
<React.Fragment key={`${item}`}>
<Chip variant="outlined" size="small" label={item} />
<br />
</React.Fragment>
Expand Down Expand Up @@ -125,7 +130,7 @@ export default function AccountsTable({ accounts, rowsPerPage, toggleSort, sort,
</TableCell>
<TableCell onClick={() => { toggleSort && toggleSort("email"); }}
style={{ cursor: "pointer" }} >
{t("Email")} {renderSort("email")}
{t("Verified")} {renderSort("verified")}
</TableCell>
<TableCell>{t("Roles")}</TableCell>
<TableCell>{t("Attributes")}</TableCell>
Expand Down
2 changes: 1 addition & 1 deletion src/views/Accounts/AccountsTablePage.js
Expand Up @@ -45,7 +45,7 @@ export default function AccountsTablePage({ location }) {
}, [page, rowsPerPage, sort]);

const updateData = () => {
ApiAccountService.getAccountList(page, rowsPerPage, query, [sort]).then(
ApiAccountService.getAccountList(page, rowsPerPage, {username:query}, [sort]).then(
({ data }) => {
setAccounts(data.data);
setTotalRows(data.count);
Expand Down
10 changes: 10 additions & 0 deletions src/views/Common/EditSkeleton.js
Expand Up @@ -30,5 +30,15 @@ const EditSkeleton = () => (
</GridItem>
</React.Fragment>
);
export const EditSkeletonShort = () => (
<React.Fragment>
<GridItem xs={12} lg={12}>
<Skeleton height={48} />
</GridItem>
<GridItem xs={12} lg={12}>
<Skeleton height={48} />
</GridItem>
</React.Fragment>
);

export default EditSkeleton;

0 comments on commit 1795939

Please sign in to comment.