Files
nice-app-web/src/entities/home/ui/day-status-box-container2.tsx
2025-11-24 14:54:12 +09:00

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>
</>
);
};