feature list customer

master
HOANGLAOTA 1 year ago
parent 93d23e5229
commit 7b348d6879
  1. 2
      public/assets/css/all.css
  2. 7
      src/App.js
  3. 2
      src/_components/Auth/InputDate/index.js
  4. 2
      src/_components/Auth/InputText/index.js
  5. 59
      src/_components/Header/HeaderMain/HeaderMain.style.scss
  6. 64
      src/_components/Header/HeaderMain/index.js
  7. 3
      src/_containers/HomePage/HomePage.style.scss
  8. 39
      src/_containers/HomePage/index.js
  9. 161
      src/_containers/ListCustomer/ListCustomer.style.scss
  10. 178
      src/_containers/ListCustomer/index.js
  11. 39
      src/_helpers/apiCaller.js

@ -10425,7 +10425,7 @@ ul.pagination li:hover a {
}
.disable-mobile {
display: none;
display: none !important;
}
.enable-mobile {

@ -11,6 +11,7 @@ import {LoginPage} from './_containers/LoginPage/index'
import { ForgotPasswordPage } from "./_containers/ForgotPasswordPage";
import RegisterPage from "./_containers/RegisterPage";
import HomePage from "./_containers/HomePage";
import ListCustomer from "./_containers/ListCustomer";
function App() {
const dispatch = useDispatch();
@ -51,6 +52,12 @@ function App() {
component={HomePage}
authentication={authentication}
/>
<RouteRedirectToLogin
path="/customers"
exact={true}
component={ListCustomer}
authentication={authentication}
/>
<Redirect from="*" to="/" />
</Switch>
</Router>

@ -23,7 +23,7 @@ const InputDate = (props) => {
};
return (
<div className="input_date_base_container">
<div className={"input_date_base_container " + props?.classNameContainer}>
{props.errorText ? (
<div className={props.errorAbsolute ? "error_text_absolute error_input" : "error_text error_input"}>
<span>{props.errorText}</span>

@ -93,7 +93,7 @@ const InputText = (props) => {
};
return (
<div className="input_text_base_container">
<div className={"input_text_base_container " + props?.classNameContainer}>
{props.errorText && props?.typeErrText != "underAbsolute" ? (
<div
className={

@ -10,7 +10,7 @@
background-color: #fff;
@include screen_mobile {
padding-right: 16px;
padding: 0 16px;
}
.logo {
@ -18,6 +18,7 @@
width: 120px;
margin: 0;
padding: 0;
scale: 130%;
}
}
@ -26,10 +27,27 @@
justify-content: space-between;
align-items: center;
height: 80px;
gap: 48px;
.list-header {
display: flex;
gap: 24px;
}
.header-item {
font-size: 18px;
text-transform: uppercase;
text-wrap: nowrap;
}
.header-item.header-item-selected {
font-weight: 700;
color: #00b9b7;
}
.btn-logout {
border-radius: 50%;
border: 2px solid #00B9B7;
border: 2px solid #666;
padding: 6px;
cursor: pointer;
position: relative;
@ -37,6 +55,10 @@
height: 36px;
display: flex;
svg {
stroke: #666;
}
.btn-logout-text {
font-size: 14px;
color: #000;
@ -52,5 +74,38 @@
border-radius: 24px;
}
}
.btn-logout:hover {
border-color: #00b9b7;
}
.btn-logout:hover svg {
stroke: #00b9b7;
}
.menu-mobile {
position: relative;
.list-header-mobile {
position: absolute;
top: 100%;
right: 0;
display: flex;
flex-direction: column;
padding: 0 16px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
background-color: #fff;
.header-item {
border-bottom: 1px solid #ccc;
padding: 16px 0;
font-size: 16px;
}
.header-item:last-child {
border-bottom: none;
}
}
}
}
}

@ -1,18 +1,60 @@
import { Link } from "react-router-dom";
import { Link, NavLink } from "react-router-dom";
import './HeaderMain.style.scss'
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import {history} from '../../../_helpers/history'
import { apiCaller } from "../../../_helpers";
export default function HeaderMain() {
const [isHoverLogout, setIsHoverLogout] = useState(false)
const [isOpenMenuMobile, setIsOpenMenuMobile] = useState(false)
const menuMobileRef = useRef();
const handleLogout = async () => {
await apiCaller('/logout', "POST", {})
window.location.href = "/login";
localStorage.removeItem("authentication");
localStorage.removeItem("access_token");
setIsOpenMenuMobile(false)
}
const renderListHeader = () => {
return (
<>
<NavLink
exact
to="/"
className={isActive =>
"header-item" + (isActive ? " header-item-selected" : "")
}
onClick={() => setIsOpenMenuMobile(false)}
>
Thông tin chung
</NavLink>
<NavLink
to="/customers"
className={isActive =>
"header-item" + (isActive ? " header-item-selected" : "")
}
onClick={() => setIsOpenMenuMobile(false)}
>
Danh sách khách hàng
</NavLink>
</>
)
}
const handleClickOutside = (event) => {
if (menuMobileRef.current && !menuMobileRef.current.contains(event.target)) {
setIsOpenMenuMobile(false);
}
};
useEffect(() => {
document.addEventListener('click', handleClickOutside, true);
return () => {
document.removeEventListener('click', handleClickOutside, true);
};
}, []);
return (
<div className="header-main-container">
<div className="sunE-container">
@ -22,11 +64,25 @@ export default function HeaderMain() {
<img src={"/assets/images/logo.png"} alt={"Logo"} />
</Link>
</div>
<div className="btn-logout" onMouseOver={() => setIsHoverLogout(true)} onMouseOut={() => setIsHoverLogout(false)} onClick={handleLogout}>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="none" stroke="#00B9B7" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8m4-9l-4-4m4 4l-4 4m4-4H9"/></svg>
<div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', flex: 1}}>
<div className="list-header disable-mobile">
{renderListHeader()}
</div>
<div className="btn-logout disable-mobile" onMouseOver={() => setIsHoverLogout(true)} onMouseOut={() => setIsHoverLogout(false)} onClick={handleLogout}>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8m4-9l-4-4m4 4l-4 4m4-4H9"/></svg>
{isHoverLogout && <span className="btn-logout-text">Đăng xuất</span>}
</div>
</div>
<div className="enable-mobile">
<div className="menu-mobile" ref={menuMobileRef}>
<svg onClick={() => setIsOpenMenuMobile(!isOpenMenuMobile)} xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24"><path fill="#404041" d="M3 18v-2h18v2zm0-5v-2h18v2zm0-5V6h18v2z"/></svg>
{isOpenMenuMobile && <div className="list-header-mobile">
{renderListHeader()}
<div className="header-item" onClick={handleLogout}>Đăng xuất</div>
</div>}
</div>
</div>
</div>
</div>
</div>
);

@ -46,7 +46,7 @@
.name-agency {
font-size: 28px;
font-weight: 700;
padding-top: 10px;
padding-top: 6px;
@include screen_mobile {
padding-top: 0;
@ -70,6 +70,7 @@
.box-link {
flex-direction: column;
.title-box-link {
font-size: 24px;
font-weight: 700;

@ -24,7 +24,8 @@ export default function HomePage() {
const authentication = useSelector((state) => state.authentication);
const handleCopy = (type, value) => {
navigator.clipboard.writeText(value)
const link = value?.trim()?.substring(0,5)?.includes('http') ? value : `https://${value?.trim()}`
navigator.clipboard.writeText(link)
if (!!isCopied?.[type]) {
return;
}
@ -52,15 +53,29 @@ export default function HomePage() {
)
}
const renderInfoAgencyItem = (text) => {
const renderIconInfoAgency = (type) => {
switch (type) {
case 'birthday':
return (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" stroke="#404041" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"><path d="M4 16.5V20a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3.5M3 14v-1a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v1m-9-6v3m0-3c1.262 0 2-.968 2-2.625S12 2 12 2s-2 1.718-2 3.375S10.738 8 12 8"/><path d="M9 14a3 3 0 1 1-6 0m12 0a3 3 0 1 1-6 0m12 0a3 3 0 1 1-6 0"/></g></svg>
);
case 'phone':
return (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 256 256"><path fill="#404041" d="m224 154.8l-47.09-21.11l-.18-.08a19.94 19.94 0 0 0-19 1.75a13 13 0 0 0-1.12.84l-22.31 19c-13-7.05-26.43-20.37-33.49-33.21l19.06-22.66a12 12 0 0 0 .85-1.15a20 20 0 0 0 1.66-18.83a1.4 1.4 0 0 1-.08-.18L101.2 32a20.06 20.06 0 0 0-20.78-11.85A60.27 60.27 0 0 0 28 80c0 81.61 66.39 148 148 148a60.27 60.27 0 0 0 59.85-52.42A20.06 20.06 0 0 0 224 154.8M176 204A124.15 124.15 0 0 1 52 80a36.29 36.29 0 0 1 28.48-35.54l18.82 42l-19.16 22.82a12 12 0 0 0-.86 1.16A20 20 0 0 0 78 130.08c9.42 19.28 28.83 38.56 48.31 48a20 20 0 0 0 19.69-1.45a12 12 0 0 0 1.11-.85l22.43-19.07l42 18.81A36.29 36.29 0 0 1 176 204"/></svg>
);
case 'email':
return (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#404041" d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2zm-2 0l-8 5l-8-5zm0 12H4V8l8 5l8-5z"/></svg>
)
default:
return null;
}
}
const renderInfoAgencyItem = (text, type) => {
return (
<div className="info-agency-item">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 32 32">
<path
fill="#00B9B7"
d="M16 3C8.832 3 3 8.832 3 16s5.832 13 13 13s13-5.832 13-13S23.168 3 16 3m0 2c6.087 0 11 4.913 11 11s-4.913 11-11 11S5 22.087 5 16S9.913 5 16 5m-1 5v5h-5v2h5v5h2v-5h5v-2h-5v-5z"
/>
</svg>
{renderIconInfoAgency(type)}
<span>{text}</span>
</div>
)
@ -103,14 +118,14 @@ export default function HomePage() {
{authentication.fullname}
</p>
<div className="sub-info-agency">
{renderInfoAgencyItem(moment(authentication.birthday).format("DD/MM/YYYY"))}
{renderInfoAgencyItem(authentication.phone)}
{renderInfoAgencyItem(authentication.email)}
{renderInfoAgencyItem(moment(authentication.birthday).format("DD/MM/YYYY"), 'birthday')}
{renderInfoAgencyItem(authentication.phone, 'phone')}
{renderInfoAgencyItem(authentication.email, 'email')}
</div>
</div>
</div>
{renderBoxLink('Link Đăng ký tuyến dưới', authentication.downline_register, homeType.REGISTER)}
{/* {renderBoxLink('Link Landing page cho khách hàng', authentication.promotional_link, homeType.LANDING)} */}
{renderBoxLink('Link Landing page cho khách hàng', authentication.promotional_link, homeType.LANDING)}
</div>
</div>
</div>

@ -0,0 +1,161 @@
@import "/src/_styles/mixin";
.main-container {
@include screen_mobile {
padding: 0 16px;
}
.filter-container {
display: flex;
flex-direction: column;
.filter-form {
display: flex;
align-items: center;
gap: 24px;
@include screen_mobile {
flex-direction: column;
gap: 0;
align-items: unset;
}
.input-base-filter {
height: 48px;
.icon_label {
margin-right: 12px;
}
}
.keyword-filter-form {
flex: 1;
}
.date-filter-form {
flex: 1;
display: flex;
gap: 24px;
@include screen_mobile {
gap: 16px;
}
}
.input-container {
flex: 1;
}
}
.filter-action {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 24px;
@include screen_mobile {
justify-content: center;
}
.btn-filter {
display: flex;
align-items: center;
height: 40px;
border-radius: 20px;
line-height: 40px;
padding: 0 25px;
font-size: 16px;
border: none;
font-family: 'Myriadpro-SemiBold';
svg {
margin-right: 8px;
}
}
.btn-cancel-filter {
color: #4b4a4a;
background-color: #DDDDDD;
}
.btn-cancel-filter:hover {
opacity: 0.6;
}
}
}
.list-customer-container {
margin-top: 64px;
.total-customer {
font-weight: 700;
margin-bottom: 16px;
}
.empty-text {
font-weight: 700;
font-size: 18px;
text-align: center;
}
.list-customer {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(48.6%, 1fr));
gap: 24px;
.customer-item {
// flex: 1 1 300px;
padding: 16px;
border-radius: 24px;
border: 1px solid #E1E1E1;
box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
.customer-name {
font-size: 24px;
font-weight: 700;
margin-bottom: 16px;
}
.customer-row {
display: flex;
gap: 16px;
margin-bottom: 8px;
}
.customer-row.message .customer-info {
width: 100%;
}
.customer-row-mobile {
@include screen_mobile {
flex-direction: column;
gap: 8px;
}
.customer-info {
@include screen_mobile {
width: 100%;
}
}
}
.customer-info {
width: 50%;
display: flex;
gap: 8px;
svg {
width: 24px;
height: 24px;
}
span {
flex: 1;
text-align: justify;
}
}
}
}
}
}

@ -0,0 +1,178 @@
import { useEffect, useState } from "react";
import InputText from "../../_components/Auth/InputText";
import HeaderMain from "../../_components/Header/HeaderMain";
import InputDate from "../../_components/Auth/InputDate";
import './ListCustomer.style.scss'
import { apiCaller } from "../../_helpers";
import { configConstants } from "../../_constants";
import dayjs from "dayjs";
export default function ListCustomer() {
const [filter, setFilter] = useState({
keyword: '',
start_date: '',
end_date: ''
})
const [listCustomer, setListCustomer] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [isFilter, setIsFilter] = useState(false)
const getData = async (dataFilter) => {
setIsLoading(true)
const endPoint = '/agent/get_customer?' +
(!!dataFilter?.keyword ? `keyword=${dataFilter.keyword}&` : '') +
(!!dataFilter?.start_date ? `start_date=${dayjs(dataFilter.start_date).format('YYYY-MM-DD')}&` : '') +
(!!dataFilter?.end_date ? `end_date=${dayjs(dataFilter.end_date).format('YYYY-MM-DD')}` : '');
try {
const res = await apiCaller(endPoint, 'GET', {}, null, false, configConstants.API_URL_SETEST, true, true)
setIsLoading(false)
if(res?.status) {
setListCustomer(res?.data)
}
} catch (err) {
setIsLoading(false)
}
}
const changeFilter = (key, value) => {
setFilter(prev => ({
...prev,
[key]: value
}))
}
const validateFilter = () => {
return !!filter.keyword || !!filter.start_date || !!filter.end_date
}
const handleCancelFilter = () => {
const iniFilter = {
end_date: '',
keyword: '',
start_date: ''
}
setIsFilter(false)
setFilter(iniFilter)
getData(iniFilter)
}
const handleFilter = () => {
setIsFilter(true)
getData(filter)
}
useEffect(() => {
getData(filter)
}, [])
const renderIconKeyWord = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 16 16"><path fill="#404041" fill-rule="evenodd" d="M0 2.965C0 1.88.88 1 1.965 1h2.807c1.085 0 1.965.88 1.965 1.965v.561c0 1.086-.88 1.965-1.965 1.965H1.965A1.965 1.965 0 0 1 0 3.526zm1.965-.28a.28.28 0 0 0-.28.28v.561a.28.28 0 0 0 .28.281h2.807a.28.28 0 0 0 .28-.28v-.562a.28.28 0 0 0-.28-.28zm6.175.561c0-.465.377-.842.842-.842h6.176a.842.842 0 1 1 0 1.684H8.982a.842.842 0 0 1-.842-.842M.28 8.298c0-.465.378-.842.843-.842H11.79a.842.842 0 1 1 0 1.684H1.123a.842.842 0 0 1-.842-.842M.28 13.35c0-.464.378-.841.843-.841h13.474a.842.842 0 1 1 0 1.684H1.123a.842.842 0 0 1-.842-.842" clip-rule="evenodd"/><path fill="#404041" d="M14.877 9.14a.842.842 0 1 0 0-1.684a.842.842 0 0 0 0 1.684"/></svg>
)
}
const renderIconDate = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 36 36"><path fill="#404041" d="M32.25 6H29v2h3v22H4V8h3V6H3.75A1.78 1.78 0 0 0 2 7.81v22.38A1.78 1.78 0 0 0 3.75 32h28.5A1.78 1.78 0 0 0 34 30.19V7.81A1.78 1.78 0 0 0 32.25 6" class="clr-i-outline clr-i-outline-path-1"/><path fill="#404041" d="M8 14h2v2H8z" class="clr-i-outline clr-i-outline-path-2"/><path fill="#404041" d="M14 14h2v2h-2z" class="clr-i-outline clr-i-outline-path-3"/><path fill="#404041" d="M20 14h2v2h-2z" class="clr-i-outline clr-i-outline-path-4"/><path fill="#404041" d="M26 14h2v2h-2z" class="clr-i-outline clr-i-outline-path-5"/><path fill="#404041" d="M8 19h2v2H8z" class="clr-i-outline clr-i-outline-path-6"/><path fill="#404041" d="M14 19h2v2h-2z" class="clr-i-outline clr-i-outline-path-7"/><path fill="#404041" d="M20 19h2v2h-2z" class="clr-i-outline clr-i-outline-path-8"/><path fill="#404041" d="M26 19h2v2h-2z" class="clr-i-outline clr-i-outline-path-9"/><path fill="#404041" d="M8 24h2v2H8z" class="clr-i-outline clr-i-outline-path-10"/><path fill="#404041" d="M14 24h2v2h-2z" class="clr-i-outline clr-i-outline-path-11"/><path fill="#404041" d="M20 24h2v2h-2z" class="clr-i-outline clr-i-outline-path-12"/><path fill="#404041" d="M26 24h2v2h-2z" class="clr-i-outline clr-i-outline-path-13"/><path fill="#404041" d="M10 10a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v6a1 1 0 0 0 1 1" class="clr-i-outline clr-i-outline-path-14"/><path fill="#404041" d="M26 10a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v6a1 1 0 0 0 1 1" class="clr-i-outline clr-i-outline-path-15"/><path fill="#404041" d="M13 6h10v2H13z" class="clr-i-outline clr-i-outline-path-16"/><path fill="none" d="M0 0h36v36H0z"/></svg>
)
}
return (
<div className="bg-main rel">
<HeaderMain />
<div className="body-home-container">
<div className="sunE-container">
<div className="main-container">
<div className="filter-container">
<div className="filter-form">
<div className="keyword-filter-form">
<InputText
classNameContainer='input-container'
className='input-base-filter'
value={filter.keyword}
setValue={(text) => changeFilter('keyword', text)}
type="text"
name="keyword"
placeholder="Nhập tên / số điện thoại / email"
autoFocus={true}
renderLabelIcon={renderIconKeyWord}
/>
</div>
<div className="date-filter-form">
<InputDate
classNameContainer='input-container'
className='input-base-filter'
value={filter.start_date}
setValue={(date) => changeFilter('start_date', date)}
name="start_date"
renderLabelIcon={renderIconDate}
placeholder={"Từ ngày"}
maxDate={new Date()}
/>
<InputDate
classNameContainer='input-container'
className='input-base-filter'
value={filter.end_date}
setValue={(date) => changeFilter('end_date', date)}
name="end_date"
renderLabelIcon={renderIconDate}
placeholder={"Đến ngày"}
maxDate={new Date()}
/>
</div>
</div>
<div className="filter-action">
<button className="btn-cancel-filter btn-filter" onClick={handleCancelFilter} disabled={!isFilter}>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24"><path fill="#4b4a4a" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8s8 3.59 8 8s-3.59 8-8 8m3.59-13L12 10.59L8.41 7L7 8.41L10.59 12L7 15.59L8.41 17L12 13.41L15.59 17L17 15.59L13.41 12L17 8.41z"/></svg>
Hủy
</button>
<button className="btn-line-blue btn-filter" onClick={handleFilter} disabled={!validateFilter()}>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/><path fill="#ffffff" d="M10.5 2a8.5 8.5 0 1 0 5.262 15.176l3.652 3.652a1 1 0 0 0 1.414-1.414l-3.652-3.652A8.5 8.5 0 0 0 10.5 2M4 10.5a6.5 6.5 0 1 1 13 0a6.5 6.5 0 0 1-13 0"/></g></svg>
Tìm kiếm
</button>
</div>
</div>
<div className="list-customer-container">
{!!listCustomer.length && <p className="total-customer">{`Tổng số khách hàng: ${listCustomer.length}`}</p>}
<div className="list-customer">
{listCustomer?.map(item => (
<div className="customer-item" key={item?.id}>
<p className="customer-name">{item?.guest_name}</p>
<div className="customer-row customer-row-mobile">
<div className="customer-info">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 256 256"><path fill="#00B9B7" d="m224 154.8l-47.09-21.11l-.18-.08a19.94 19.94 0 0 0-19 1.75a13 13 0 0 0-1.12.84l-22.31 19c-13-7.05-26.43-20.37-33.49-33.21l19.06-22.66a12 12 0 0 0 .85-1.15a20 20 0 0 0 1.66-18.83a1.4 1.4 0 0 1-.08-.18L101.2 32a20.06 20.06 0 0 0-20.78-11.85A60.27 60.27 0 0 0 28 80c0 81.61 66.39 148 148 148a60.27 60.27 0 0 0 59.85-52.42A20.06 20.06 0 0 0 224 154.8M176 204A124.15 124.15 0 0 1 52 80a36.29 36.29 0 0 1 28.48-35.54l18.82 42l-19.16 22.82a12 12 0 0 0-.86 1.16A20 20 0 0 0 78 130.08c9.42 19.28 28.83 38.56 48.31 48a20 20 0 0 0 19.69-1.45a12 12 0 0 0 1.11-.85l22.43-19.07l42 18.81A36.29 36.29 0 0 1 176 204"/></svg>
<span>{item?.phone}</span>
</div>
<div className="customer-info">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="#00B9B7" d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2zm-2 0l-8 5l-8-5zm0 12H4V8l8 5l8-5z"/></svg>
<span>{item?.email}</span>
</div>
</div>
<div className="customer-row">
<div className="customer-info">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="#00B9B7" d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1a6.887 6.887 0 0 0 0 9.8c2.73 2.7 7.15 2.7 9.88 0c1.36-1.35 2.04-2.92 2.04-4.9h2c0 1.98-.88 4.55-2.64 6.29c-3.51 3.48-9.21 3.48-12.72 0c-3.5-3.47-3.53-9.11-.02-12.58a8.987 8.987 0 0 1 12.65 0L21 3zM12.5 8v4.25l3.5 2.08l-.72 1.21L11 13V8z"/></svg>
<span>{dayjs(item?.date_receive).format('DD/MM/YYYY')}</span>
</div>
{!!item?.grade && <div className="customer-info">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 32 32"><path fill="#00B9B7" d="m16 7.78l-.313.095l-12.5 4.188L.345 13L2 13.53v8.75c-.597.347-1 .98-1 1.72a2 2 0 1 0 4 0c0-.74-.403-1.373-1-1.72v-8.06l2 .655V20c0 .82.5 1.5 1.094 1.97c.594.467 1.332.797 2.218 1.093c1.774.59 4.112.937 6.688.937c2.576 0 4.914-.346 6.688-.938c.886-.295 1.624-.625 2.218-1.093C25.5 21.5 26 20.82 26 20v-5.125l2.813-.938L31.655 13l-2.843-.938l-12.5-4.187zm0 2.095L25.375 13L16 16.125L6.625 13zm-8 5.688l7.688 2.562l.312.094l.313-.095L24 15.562V20c0 .01.004.126-.313.375c-.316.25-.883.565-1.625.813C20.58 21.681 18.395 22 16 22c-2.395 0-4.58-.318-6.063-.813c-.74-.247-1.308-.563-1.624-.812C7.995 20.125 8 20.01 8 20z"/></svg>
<span>{`Lớp ${item?.grade}`}</span>
</div>}
</div>
{item?.message && <div className="customer-row customer-row-mobile message">
<div className="customer-info">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="#00B9B7" d="M4 4h16v12H5.17L4 17.17zm0-2c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm2 10h12v2H6zm0-3h12v2H6zm0-3h12v2H6z"/></svg>
<span>{item?.message}</span>
</div>
</div>}
</div>
))}
</div>
{!listCustomer.length && !isLoading && <p className="empty-text">Không dữ liệu.</p>}
</div>
</div>
</div>
</div>
</div>
)
}

@ -18,24 +18,25 @@ export function apiCaller(
isLoading = true,
isFullResponse = false,
) {
if (headers === undefined || headers === null) {
// if (headers === undefined || headers === null) {
headers = {
"X-API-KEY": configConstants.API_KEY,
Authorization: `Bearer ${JSON.parse(localStorage.getItem("access_token"))}`,
};
if (localStorage.getItem("authentication")) {
let authentication = JSON.parse(localStorage.getItem("authentication"));
headers["jwt_token"] = authentication.jwt_token;
}
} else {
if (localStorage.getItem("authentication")) {
let authentication = JSON.parse(localStorage.getItem("authentication"));
headers["jwt_token"] = authentication.jwt_token;
}
headers = {
"X-API-KEY": configConstants.API_KEY,
...headers,
}
}
// if (localStorage.getItem("authentication")) {
// let authentication = JSON.parse(localStorage.getItem("authentication"));
// headers["jwt_token"] = authentication.jwt_token;
// }
// } else {
// if (localStorage.getItem("authentication")) {
// let authentication = JSON.parse(localStorage.getItem("authentication"));
// headers["jwt_token"] = authentication.jwt_token;
// }
// headers = {
// "X-API-KEY": configConstants.API_KEY,
// ...headers,
// }
// }
if (isLoading) {
$(".loading").removeClass("hide");
}
@ -43,10 +44,10 @@ export function apiCaller(
method,
timeout: configConstants.API_TIMEOUT,
url: `${basUrl}${endpoint}`,
auth: {
username: configConstants.AUTH_BASIC_USER_NAME,
password: configConstants.AUTH_BASIC_PASSWORD,
},
// auth: {
// username: configConstants.AUTH_BASIC_USER_NAME,
// password: configConstants.AUTH_BASIC_PASSWORD,
// },
data: body,
headers: headers,
})

Loading…
Cancel
Save