258 lines
9.6 KiB
TypeScript
258 lines
9.6 KiB
TypeScript
import moment from 'moment';
|
|
import { useEffect, useState } from 'react';
|
|
import { IMAGE_ROOT } from '@/shared/constants/common';
|
|
import { HomeMonthParams, HomeMonthResponse, HomeOverviewParams, HomeOverviewResponse, Sales, Settlement, TopPaymentMethodInfo, TopSalesDayInfo, TopSalesTimeInfo } from '../model/types';
|
|
import { useHomeOverviewMutation } from '../api/use-home-overview-mutation';
|
|
import { useHomeMonthwMutation } from '../api/use-home-month-mutation';
|
|
import { useNavigate } from '@/shared/lib/hooks';
|
|
import { PATHS } from '@/shared/constants/paths';
|
|
import { useNewMidStore, useStore } from '@/shared/model/store';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { showAlert } from '@/widgets/show-alert';
|
|
import { checkGrant } from '@/shared/lib/check-grant';
|
|
import { snackBar } from '@/shared/lib';
|
|
|
|
export const BoxContainer2 = () => {
|
|
const { navigate } = useNavigate();
|
|
const { t, i18n } = useTranslation();
|
|
const { newMid } = useNewMidStore();
|
|
|
|
const [mid, setMid] = useState<string>();
|
|
const [searchMonth, setSearchMonth] = useState<string>(moment().format('YYYYMM'));
|
|
const [searchDate, setSearchDate] = useState<string>(moment().format('YYYYMMDD'));
|
|
|
|
const [sales, setSales] = useState<Sales>();
|
|
const [settlement, setSettlement] = useState<Settlement>();
|
|
const [salesIncrease, setSalesIncrease] = useState<number>();
|
|
const [settlementIncrease, setSettlementIncrease] = useState<number>();
|
|
|
|
const [averageTransactionAmount, setAverageTransactionAmount] = useState<number>();
|
|
const [dailyAverageSales, setDailyAverageSales] = useState<number>();
|
|
const [dailyAverageCount, setDailyAverageCount] = useState<number>();
|
|
const [topSalesDayInfo, setTopSalesDayInfo] = useState<TopSalesDayInfo>();
|
|
const [topSalesTimeInfo, setTopSalesTimeInfo] = useState<TopSalesTimeInfo>();
|
|
const [topPaymentMethodInfo, setTopPaymentMethodInfo] = useState<TopPaymentMethodInfo>();
|
|
|
|
const { mutateAsync: homeMonth } = useHomeMonthwMutation();
|
|
const { mutateAsync: homeOverview } = useHomeOverviewMutation();
|
|
|
|
const callMonth = () => {
|
|
let params: HomeMonthParams = {
|
|
searchDate: searchMonth,
|
|
mid: mid,
|
|
};
|
|
homeMonth(params).then((rs: HomeMonthResponse) => {
|
|
setSales(rs.sales);
|
|
setSettlement(rs.settlement);
|
|
|
|
let currentMonthAmount = rs.sales.currentMonthAmount;
|
|
let previousMonthAmount = rs.sales.previousMonthAmount;
|
|
if(currentMonthAmount && previousMonthAmount){
|
|
let increase = (currentMonthAmount - previousMonthAmount) / previousMonthAmount * 100;
|
|
increase = Math.round(increase * 100) / 100;
|
|
setSalesIncrease(increase);
|
|
}
|
|
|
|
let currentMonthSettlementAmount = rs.settlement.currentMonthSettlementAmount;
|
|
let previousMonthSettlementAmount = rs.settlement.previousMonthSettlementAmount;
|
|
if(currentMonthSettlementAmount && previousMonthSettlementAmount){
|
|
let increase = (currentMonthSettlementAmount - previousMonthSettlementAmount) / previousMonthSettlementAmount * 100;
|
|
increase = Math.round(increase * 100) / 100;
|
|
setSettlementIncrease(increase);
|
|
}
|
|
}).catch((e: any) => {
|
|
if(e.response?.data?.error?.message){
|
|
snackBar(e.response?.data?.error?.message);
|
|
return;
|
|
}
|
|
});
|
|
};
|
|
|
|
const callOverview = () => {
|
|
let params: HomeOverviewParams = {
|
|
searchDate: searchDate,
|
|
mid: mid,
|
|
};
|
|
homeOverview(params).then((rs: HomeOverviewResponse) => {
|
|
setAverageTransactionAmount(rs.averageTransactionAmount);
|
|
setDailyAverageSales(rs.dailyAverageSales);
|
|
setDailyAverageCount(rs.dailyAverageCount);
|
|
setTopSalesDayInfo(rs.topSalesDayInfo);
|
|
setTopSalesTimeInfo(rs.topSalesTimeInfo);
|
|
setTopPaymentMethodInfo(rs.topPaymentMethodInfo);
|
|
}).catch((e: any) => {
|
|
if(e.response?.data?.error?.message){
|
|
snackBar(e.response?.data?.error?.message);
|
|
return;
|
|
}
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
const userMid = useStore.getState().UserStore.mid;
|
|
setMid(userMid);
|
|
}, []);
|
|
useEffect(() => {
|
|
if(!!mid){
|
|
callMonth();
|
|
callOverview();
|
|
}
|
|
}, [mid]);
|
|
useEffect(() => {
|
|
if(!!newMid){
|
|
setMid(newMid);
|
|
}
|
|
}, [newMid]);
|
|
|
|
const onClickToNavigate = (path: string) => {
|
|
if(path === 'allTransaction'){
|
|
if(checkGrant(32, 'R')){
|
|
navigate(PATHS.transaction.allTransaction.list);
|
|
}
|
|
else{
|
|
showAlert(t('common.nopermission'));
|
|
}
|
|
}
|
|
else if(path === 'settlement'){
|
|
if(checkGrant(36, 'R')){
|
|
navigate(PATHS.settlement.list);
|
|
}
|
|
else{
|
|
showAlert(t('common.nopermission'));
|
|
}
|
|
}
|
|
};
|
|
|
|
const translateDayOfWeek = (koreanDay: string): string => {
|
|
if (i18n.language !== 'en') return koreanDay;
|
|
|
|
const dayMap: { [key: string]: string } = {
|
|
'월요일': 'Monday',
|
|
'화요일': 'Tuesday',
|
|
'수요일': 'Wednesday',
|
|
'목요일': 'Thursday',
|
|
'금요일': 'Friday',
|
|
'토요일': 'Saturday',
|
|
'일요일': 'Sunday'
|
|
};
|
|
|
|
return dayMap[koreanDay] || koreanDay;
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div>
|
|
<div className="section-header">
|
|
<h3>{t('home.salesSettlementStatus')}</h3>
|
|
<p>({t('home.comparedToPreviousMonth')})</p>
|
|
</div>
|
|
<div className="box-wrap two-sales">
|
|
<h4>{t('home.totalSales')}</h4>
|
|
<div className="today-sales mt-sty">
|
|
<span className="won01">
|
|
{t('home.money', { value: new Intl.NumberFormat('en-US').format(sales?.currentMonthAmount || 0) })}
|
|
</span>
|
|
<span className={ `per ${(salesIncrease && salesIncrease >= 0)? 'plus': 'minus'}` }>
|
|
{ (salesIncrease && salesIncrease >= 0)? '↑ ' :'↓ ' }
|
|
{new Intl.NumberFormat('en-US').format(Math.abs(salesIncrease || 0))}%
|
|
</span>
|
|
<a className="arrow">
|
|
<img
|
|
src={ IMAGE_ROOT + '/ico_arrow.svg' }
|
|
alt={t('home.goToSales')}
|
|
onClick={ () => onClickToNavigate('allTransaction') }
|
|
/>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div className="box-wrap two-sales">
|
|
<h4>{t('home.totalSettlement')}</h4>
|
|
<div className="today-sales mt-sty">
|
|
<span className="won02">
|
|
{t('home.money', { value: new Intl.NumberFormat('en-US').format(settlement?.currentMonthSettlementAmount || 0) })}
|
|
</span>
|
|
<span className={ `per ${(settlementIncrease && settlementIncrease >= 0)? 'plus': 'minus'}` }>
|
|
{(settlementIncrease && settlementIncrease >= 0) ? '↑ ' : '↓ '}
|
|
{new Intl.NumberFormat('en-US').format(Math.abs(settlementIncrease || 0))}%
|
|
</span>
|
|
<a className="arrow">
|
|
<img
|
|
src={ IMAGE_ROOT + '/ico_arrow.svg' }
|
|
alt={t('home.goToSales')}
|
|
onClick={ () => onClickToNavigate('settlement') }
|
|
/>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="section-header">
|
|
<h3>{t('home.transactionInsights')}</h3>
|
|
<p>({t('home.basedOnLastWeek')})</p>
|
|
</div>
|
|
<div className="box-wrap two-sales img-customer">
|
|
<h4>{t('home.averageTransactionAmount')}</h4>
|
|
<div className="two-account">
|
|
<span>
|
|
{t('home.money', { value: new Intl.NumberFormat('en-US').format(averageTransactionAmount || 0) })}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="box-wrap two-sales img-states">
|
|
<h4>{t('home.dailyAverageSalesAndCount')}</h4>
|
|
<div className="two-account">
|
|
<span>
|
|
{t('home.money', { value: new Intl.NumberFormat('en-US').format(dailyAverageSales || 0) })}
|
|
({t('home.count', { value: new Intl.NumberFormat('en-US').format(dailyAverageCount || 0) })})
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="box-wrap ranking">
|
|
<h4>{t('home.topSalesDays')}</h4>
|
|
<ul>
|
|
{
|
|
topSalesDayInfo?.daySalesRatios.map((value, index) => (
|
|
<li key={`key-day-sales-ratio-${index}`}>
|
|
<span className={ `ranking-num-${(index === 0)? '01': 'ot'}` }>{ (index + 1) }</span>
|
|
<span>{ translateDayOfWeek(value.dayOfWeek) }</span>
|
|
<span className="last-per-01">{ value.ratio + '%' }</span>
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
</div>
|
|
<div className="box-wrap ranking">
|
|
<h4>{t('home.topSalesHours')}</h4>
|
|
<ul>
|
|
{
|
|
topSalesTimeInfo?.timeSalesRatios.map((value, index) => (
|
|
<li key={`key-time-sales-ratio-${index}`}>
|
|
<span className={ `ranking-num-${(index === 0)? '01': 'ot'}` }>{ (index + 1) }</span>
|
|
<span>{ value.hour }</span>
|
|
<span className="last-per-01">{ value.ratio + '%' }</span>
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
</div>
|
|
<div className="box-wrap ranking">
|
|
<h4>{t('home.topPaymentMethods')}</h4>
|
|
<ul>
|
|
{
|
|
topPaymentMethodInfo?.paymentMethodRatios.map((value, index) => (
|
|
<li key={`key-payment-method-ratio-${index}`}>
|
|
<span className={ `ranking-num-${(index === 0)? '01': 'ot'}` }>{ (index + 1) }</span>
|
|
<span>{ value.paymentMethod }</span>
|
|
<span className="last-per-01">{ value.ratio + '%' }</span>
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|