233 lines
7.4 KiB
Python
233 lines
7.4 KiB
Python
import React, { Fragment } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import classNames from 'classnames';
|
|
import { Link } from 'react-router-dom';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import {
|
|
Badge,
|
|
Card,
|
|
CardBody,
|
|
CardFooter,
|
|
CardHeader,
|
|
Col,
|
|
DropdownItem,
|
|
DropdownMenu,
|
|
DropdownToggle,
|
|
Media,
|
|
Row,
|
|
UncontrolledDropdown
|
|
} from 'reactstrap';
|
|
import Loader from '../common/Loader';
|
|
import ButtonIcon from '../common/ButtonIcon';
|
|
import FalconCardHeader from '../common/FalconCardHeader';
|
|
import FalconCardFooterLink from '../common/FalconCardFooterLink';
|
|
import useFakeFetch from '../../hooks/useFakeFetch';
|
|
import { isIterableArray } from '../../helpers/utils';
|
|
import createMarkup from '../../helpers/createMarkup';
|
|
import rawCustomer from '../../data/customer/customer';
|
|
import rawCustomerLogs from '../../data/customer/customerLogs';
|
|
|
|
const CustomerSummary = () => {
|
|
const { loading, data: customer } = useFakeFetch(rawCustomer);
|
|
const { name, email, createdAt } = customer;
|
|
|
|
return (
|
|
<Card className="mb-3">
|
|
{loading ? (
|
|
<Loader />
|
|
) : (
|
|
<Fragment>
|
|
<CardHeader>
|
|
<Row>
|
|
<Col>
|
|
<h5 className="mb-2">
|
|
{name} (<a href={`mailto:${email}`}>{email}</a>)
|
|
</h5>
|
|
<ButtonIcon color="falcon-default" size="sm" icon="plus" iconClassName="fs--2">
|
|
Add note
|
|
</ButtonIcon>
|
|
|
|
<UncontrolledDropdown className="d-inline-block ml-2">
|
|
<DropdownToggle color="falcon-default" size="sm">
|
|
<FontAwesomeIcon icon="ellipsis-h" />
|
|
</DropdownToggle>
|
|
<DropdownMenu>
|
|
<DropdownItem>Edit</DropdownItem>
|
|
<DropdownItem>Report</DropdownItem>
|
|
<DropdownItem>Archive</DropdownItem>
|
|
<DropdownItem divider />
|
|
<DropdownItem className="text-danger">Delete user</DropdownItem>
|
|
</DropdownMenu>
|
|
</UncontrolledDropdown>
|
|
</Col>
|
|
<Col xs="auto" className="d-none d-sm-block">
|
|
<h6 className="text-uppercase text-600">
|
|
Customer
|
|
<FontAwesomeIcon icon="user" className="ml-2" />
|
|
</h6>
|
|
</Col>
|
|
</Row>
|
|
</CardHeader>
|
|
<CardBody className="border-top">
|
|
<Media>
|
|
<FontAwesomeIcon icon="user" transform="down-5" className="text-success mr-2" />
|
|
<Media body>
|
|
<p className="mb-0">Customer was created</p>
|
|
<p className="fs--1 mb-0 text-600">{createdAt}</p>
|
|
</Media>
|
|
</Media>
|
|
</CardBody>
|
|
</Fragment>
|
|
)}
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
const CustomerDetailRow = ({ title, isLastItem, children }) => (
|
|
<Row>
|
|
<Col xs={5} sm={4}>
|
|
<p
|
|
className={classNames('font-weight-semi-bold', {
|
|
'mb-0': isLastItem,
|
|
'mb-1': !isLastItem
|
|
})}
|
|
>
|
|
{title}
|
|
</p>
|
|
</Col>
|
|
<Col>{children}</Col>
|
|
</Row>
|
|
);
|
|
|
|
CustomerDetailRow.propTypes = {
|
|
title: PropTypes.string.isRequired,
|
|
children: PropTypes.node.isRequired,
|
|
isLastItem: PropTypes.bool
|
|
};
|
|
|
|
CustomerDetailRow.defaultProps = { last: false };
|
|
|
|
const CustomerDetail = () => {
|
|
const { loading, data: customer } = useFakeFetch(rawCustomer);
|
|
const { id, email, createdAt, description, vat_no, email_to, address, cell, invoice_prefix } = customer;
|
|
|
|
return (
|
|
<Card className="mb-3">
|
|
<FalconCardHeader title="Details">
|
|
<ButtonIcon tag={Link} color="falcon-default" size="sm" icon="pencil-alt" to="#!" iconClassName="fs--2">
|
|
Update details
|
|
</ButtonIcon>
|
|
</FalconCardHeader>
|
|
<CardBody className="bg-light border-top">
|
|
{loading ? (
|
|
<Loader />
|
|
) : (
|
|
<Row>
|
|
<Col lg className="col-xxl-5">
|
|
<h6 className="font-weight-semi-bold ls mb-3 text-uppercase">Account Information</h6>
|
|
<CustomerDetailRow title="ID">{id}</CustomerDetailRow>
|
|
<CustomerDetailRow title="Created">{createdAt}</CustomerDetailRow>
|
|
<CustomerDetailRow title="Email">
|
|
<a href={`mailto:${email}`}>{email}</a>
|
|
</CustomerDetailRow>
|
|
<CustomerDetailRow title="Description">
|
|
{description ? description : <p className="font-italic text-400 mb-1">No Description</p>}
|
|
</CustomerDetailRow>
|
|
<CustomerDetailRow title="VAT number" isLastItem>
|
|
{vat_no ? vat_no : <p className="font-italic text-400 mb-0">No VAT Number</p>}
|
|
</CustomerDetailRow>
|
|
</Col>
|
|
<Col lg className="col-xxl-5 mt-4 mt-lg-0 offset-xxl-1">
|
|
<h6 className="font-weight-semi-bold ls mb-3 text-uppercase">Billing Information</h6>
|
|
<CustomerDetailRow title="Send email to">
|
|
<a href={`mailto:${email_to}`}>{email_to}</a>
|
|
</CustomerDetailRow>
|
|
<CustomerDetailRow title="Address">
|
|
<p className="mb-1" dangerouslySetInnerHTML={createMarkup(address)} />
|
|
</CustomerDetailRow>
|
|
<CustomerDetailRow title="Phone number">
|
|
<a href={`tel:${cell}`}>{cell}</a>
|
|
</CustomerDetailRow>
|
|
<CustomerDetailRow title="Invoice prefix" isLastItem>
|
|
<p className="font-weight-semi-bold mb-0">{invoice_prefix}</p>
|
|
</CustomerDetailRow>
|
|
</Col>
|
|
</Row>
|
|
)}
|
|
</CardBody>
|
|
<CardFooter className="border-top text-right">
|
|
<ButtonIcon tag={Link} color="falcon-default" size="sm" icon="dollar-sign" to="#!" iconClassName="fs--2">
|
|
Refund
|
|
</ButtonIcon>
|
|
<ButtonIcon
|
|
tag={Link}
|
|
color="falcon-default"
|
|
size="sm"
|
|
icon="check"
|
|
className="ml-2"
|
|
to="#!"
|
|
iconClassName="fs--2"
|
|
>
|
|
Save changes
|
|
</ButtonIcon>
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
const CustomerLog = ({ status, link, time }) => {
|
|
let badgeColor = 'soft-warning';
|
|
if (status === 404) badgeColor = 'soft-danger';
|
|
else if (status === 200) badgeColor = 'soft-success';
|
|
|
|
return (
|
|
<Row noGutters className="align-items-center border-bottom py-2 px-3">
|
|
<Col md="auto" className="pr-3">
|
|
<Badge color={badgeColor} pill>
|
|
{status}
|
|
</Badge>
|
|
</Col>
|
|
<Col md className="mt-1 mt-md-0">
|
|
<code>POST {link}</code>
|
|
</Col>
|
|
<Col md="auto">
|
|
<p className="mb-0">{time}</p>
|
|
</Col>
|
|
</Row>
|
|
);
|
|
};
|
|
|
|
CustomerLog.propTypes = {
|
|
status: PropTypes.number.isRequired,
|
|
link: PropTypes.string.isRequired,
|
|
time: PropTypes.string.isRequired
|
|
};
|
|
|
|
const CustomerLogs = () => {
|
|
const { loading, data: customerLogs } = useFakeFetch(rawCustomerLogs);
|
|
|
|
return (
|
|
<Card>
|
|
<FalconCardHeader title="Logs" />
|
|
<CardBody className="border-top p-0">
|
|
{loading ? (
|
|
<Loader />
|
|
) : (
|
|
isIterableArray(customerLogs) && customerLogs.map((log, index) => <CustomerLog {...log} key={index} />)
|
|
)}
|
|
</CardBody>
|
|
<FalconCardFooterLink title="View more logs" to="#!" borderTop={false} />
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
const CustomerDetails = () => (
|
|
<Fragment>
|
|
<CustomerSummary />
|
|
<CustomerDetail />
|
|
<CustomerLogs />
|
|
</Fragment>
|
|
);
|
|
|
|
export default CustomerDetails;
|