- Convert detail pages to modal components for better UX - Fix seq type from string to number for ARS and Alimtalk - Add seq field to list item types - Fix validation for card number input (remove formatting chars) - Fix SMS payment resend seq parameter issue - Improve z-index handling for snackBar and dialogs - Add useSetHeaderTitle to link payment history wrap - Remove unused detail page files - Update payout filter and various detail components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
191 lines
9.0 KiB
TypeScript
191 lines
9.0 KiB
TypeScript
import moment from 'moment';
|
|
import { motion } from 'framer-motion';
|
|
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
|
import { useEffect, useState } from 'react';
|
|
import { getArsOrderStatusName, getArsPaymentStatusName } from '@/entities/additional-service/model/ars/constant';
|
|
import { ArsPaymentMethod, ExtensionArsDetailParams, ExtensionArsDetailResponse, ExtensionArsResendParams, ExtensionArsResendResponse } from "@/entities/additional-service/model/ars/types";
|
|
import { useTranslation } from "react-i18next";
|
|
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
|
import { useExtensionArsDetailMutation } from '@/entities/additional-service/api/ars/use-extension-ars-detail-mutation';
|
|
import { useExtensionArsResendMutation } from '@/entities/additional-service/api/ars/use-extension-ars-resend-mutation';
|
|
import { snackBar } from '@/shared/lib';
|
|
import { ArsResendSmsBottomSheet } from '../resend-sms-bottom-sheet';
|
|
import { showAlert } from '@/widgets/show-alert';
|
|
|
|
export interface ArsDetailProps {
|
|
detailOn: boolean;
|
|
setDetailOn: (detailOn: boolean) => void;
|
|
mid: string;
|
|
tid: string;
|
|
};
|
|
|
|
export const ArsDetail = ({
|
|
detailOn,
|
|
setDetailOn,
|
|
mid,
|
|
tid
|
|
}: ArsDetailProps) => {
|
|
const { t } = useTranslation();
|
|
|
|
const [detail, setDetail] = useState<ExtensionArsDetailResponse>();
|
|
const [bottomSheetOn, setBottomSheetOn] = useState<boolean>(false);
|
|
|
|
const { mutateAsync: extensionArsDetail } = useExtensionArsDetailMutation();
|
|
const { mutateAsync: extensionArsResend } = useExtensionArsResendMutation();
|
|
|
|
const callDetail = () => {
|
|
let arsDetailParams: ExtensionArsDetailParams = {
|
|
mid: mid,
|
|
tid: tid
|
|
};
|
|
extensionArsDetail(arsDetailParams).then((rs: ExtensionArsDetailResponse) => {
|
|
setDetail(rs);
|
|
}).catch((e: any) => {
|
|
if (e.response?.data?.error?.message) {
|
|
showAlert(e.response?.data?.error?.message);
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
|
|
const arsResend = () => {
|
|
let arsResendParams: ExtensionArsResendParams = {
|
|
mid: mid,
|
|
tid: tid
|
|
};
|
|
extensionArsResend(arsResendParams).then((rs: ExtensionArsResendResponse) => {
|
|
if (rs.status) {
|
|
snackBar(t('additionalService.ars.smsResendSuccess'));
|
|
setBottomSheetOn(false);
|
|
callDetail(); // 상세 정보 갱신
|
|
} else {
|
|
const errorMessage = rs.error?.message || t('additionalService.ars.smsResendFailed');
|
|
snackBar(`[${t('common.failed')}] ${errorMessage}`);
|
|
}
|
|
}).catch((error) => {
|
|
const errorMessage = error?.response?.data?.error?.message ||
|
|
error?.message ||
|
|
t('additionalService.ars.smsResendError');
|
|
snackBar(`[${t('common.failed')}] ${errorMessage}`);
|
|
});
|
|
}
|
|
|
|
const onClickToOpenResendBottomSheet = () => {
|
|
setBottomSheetOn(true);
|
|
};
|
|
const onClickToClose = () => {
|
|
setDetailOn(false);
|
|
};
|
|
|
|
const getDate = (date?: string) => {
|
|
return (date) ? moment(date.substr(0, 8)).format('YYYY.MM.DD') : '';
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!!mid && !!tid) {
|
|
callDetail();
|
|
}
|
|
}, [mid, tid]);
|
|
|
|
return (
|
|
<>
|
|
<motion.div
|
|
className="full-menu-modal"
|
|
initial="hidden"
|
|
animate={(detailOn) ? 'visible' : 'hidden'}
|
|
variants={DetailMotionVariants}
|
|
transition={DetailMotionDuration}
|
|
style={DetailMotionStyle}
|
|
>
|
|
<div className="full-menu-container pdw-16">
|
|
<div className="full-menu-header">
|
|
<div className="full-menu-title center">{t('additionalService.ars.detailTitle')}</div>
|
|
<div className="full-menu-actions">
|
|
<FullMenuClose
|
|
addClass="full-menu-close"
|
|
onClickToCallback={onClickToClose}
|
|
></FullMenuClose>
|
|
</div>
|
|
</div>
|
|
<div className="pay-top">
|
|
<div className="num-amount">
|
|
<span className="amount">
|
|
{t('home.money', { value: new Intl.NumberFormat('en-US').format(Number(detail?.amount) || 0) })}
|
|
</span>
|
|
</div>
|
|
<div className="num-store">{detail?.corpName}</div>
|
|
<div className="num-day">{getDate(detail?.paymentDate)}</div>
|
|
</div>
|
|
<div className="detail-divider"></div>
|
|
<div className="pay-detail">
|
|
<div className="detail-title">{t('additionalService.ars.transactionInfo')}</div>
|
|
<ul className="kv-list">
|
|
<li className="kv-row">
|
|
<span className="k">{t('transaction.fields.mid')}</span>
|
|
<span className="v">{detail?.mid}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.paymentMethod')}</span>
|
|
<span className="v">{detail?.arsPaymentMethod}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.paymentStatus')}</span>
|
|
<span className="v">{getArsPaymentStatusName(t)(detail?.paymentStatus)}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.orderStatus')}</span>
|
|
<span className="v">{getArsOrderStatusName(t)(detail?.orderStatus)}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.orderDateTime')}</span>
|
|
<span className="v">{
|
|
detail?.paymentDate ? moment(detail.paymentDate, 'YYYYMMDDHHmmss').format('YYYY.MM.DD HH:mm:ss') : '-'
|
|
}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.productName')}</span>
|
|
<span className="v">{detail?.goodsName}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.orderNumber')}</span>
|
|
<span className="v">{detail?.tid}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.buyer')}</span>
|
|
<span className="v">{detail?.buyerName}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.phoneNumber')}</span>
|
|
<span className="v">{detail?.maskPhoneNumber}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.email')}</span>
|
|
<span className="v">{detail?.email}</span>
|
|
</li>
|
|
<li className="kv-row">
|
|
<span className="k">{t('additionalService.ars.sendVerificationCode')}</span>
|
|
<span className="v">{detail?.smsVerificationCode}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
{detail?.arsPaymentMethod === ArsPaymentMethod.SMS && (
|
|
<div className="apply-row">
|
|
<button
|
|
className="btn-50 btn-blue flex-1"
|
|
onClick={() => onClickToOpenResendBottomSheet()}
|
|
//disabled={ detail?.orderStatus !== OrderStatus.PENDING }
|
|
>{t('additionalService.ars.smsResend')}</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<ArsResendSmsBottomSheet
|
|
setBottomSheetOn={setBottomSheetOn}
|
|
bottomSheetOn={bottomSheetOn}
|
|
phoneNumber={detail?.phoneNumber}
|
|
callResendSms={arsResend}
|
|
></ArsResendSmsBottomSheet>
|
|
</motion.div>
|
|
</>
|
|
)
|
|
|
|
} |