첫 커밋

This commit is contained in:
focp212@naver.com
2025-09-05 15:36:48 +09:00
commit 05238b04c1
825 changed files with 176358 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
export const AllTransactionAllCancel = () => {
return (
<>
<div className="form-section">
<div className="form-group">
<label className="form-label"> </label>
<div className="input-wrapper wid-100 error">
<input
className="wid-100 align-right"
type="password"
value="2736356352"
/>
</div>
</div>
<div className="error-msg"> </div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<select className="wid-100 align-right">
<option></option>
<option>KB국민은행</option>
<option>22323213123</option>
</select>
</div>
</div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<input
className="form-input wid-100"
type="text"
placeholder=""
/>
</div>
</div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<input
className="form-input wid-100"
type="text"
placeholder=""
/>
</div>
</div>
<div className="notice-text wid-100">
<p> .<br /> .</p>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,31 @@
import { AllTransactionListProps } from '../model/types';
import { ListDateGroup } from './list-date-group';
export const AllTransactionList = ({
pageType,
listItems
}: AllTransactionListProps) => {
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
rs.push(
<ListDateGroup
pageType={ pageType }
key={ key }
date={ key }
items={ value }
></ListDateGroup>
);
}
return rs;
};
return (
<>
<div className="transaction-list">
{ getListDateGroup() }
</div>
</>
);
};

View File

@@ -0,0 +1,124 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
export const AllTransactionPartCancel = () => {
return (
<>
<div className="tb_both">
<table className="partial-cancel-table">
<colgroup>
<col width="30%" />
<col width="30%" />
<col width="40%" />
</colgroup>
<thead>
<tr>
<th className="header-empty"></th>
<th className="header-balance"></th>
<th className="header-cancel"></th>
</tr>
</thead>
<tbody>
<tr>
<td className="row-label"></td>
<td className="row-balance">555,550,000</td>
<td className="row-cancel">
<input
className="cancel-input"
type="text"
value=""
/>
</td>
</tr>
<tr>
<td className="row-label"></td>
<td className="row-balance">50,000</td>
<td className="row-cancel">
<input
className="cancel-input"
type="text"
placeholder=""
/>
</td>
</tr>
<tr>
<td className="row-label"></td>
<td className="row-balance">50,000</td>
<td className="row-cancel">
<input
className="cancel-input"
type="text"
placeholder=""
/>
</td>
</tr>
<tr>
<td className="row-label"></td>
<td className="row-balance">50,000</td>
<td className="row-cancel">
<input
className="cancel-input"
type="text"
placeholder=""
/>
</td>
</tr>
</tbody>
</table>
</div>
<div className="form-section">
<div className="form-group">
<label className="form-label"> </label>
<div className="input-wrapper wid-100 error">
<input
className="wid-100 align-right"
type="password"
value=""
/>
</div>
</div>
<div className="error-msg"> </div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<select className="wid-100 align-right">
<option></option>
<option>KB국민은행</option>
<option>22323213123</option>
</select>
</div>
</div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<input
className="form-input wid-100"
type="text"
placeholder=""
/>
</div>
</div>
<div className="form-group">
<label className="form-label"></label>
<div className="input-wrapper wid-100">
<input
className="form-input wid-100"
type="text"
placeholder=""
/>
</div>
</div>
<div className="notice-text wid-100">
<p> .<br /> .</p>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,44 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { BillingListProps } from '../model/types';
import { ListDateGroup } from './list-date-group';
export const BillingList = ({
pageType,
listItems
}: BillingListProps) => {
const { navigate } = useNavigate();
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
rs.push(
<ListDateGroup
pageType={ pageType }
key={ key }
date={ key }
items={ value }
></ListDateGroup>
);
}
return rs;
};
const onClickToNavigate = () => {
navigate(PATHS.transaction.billing.paymentRequest);
};
return (
<>
<div className="transaction-list">
{ getListDateGroup() }
<div className="apply-row bottom-padding">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
> </button>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,43 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
export const BottomSheetChangesCashReceitUses = () => {
return (
<>
<div className="bg-dim"></div>
<div className="bottomsheet">
<div className="bottomsheet-header">
<div className="bottomsheet-title">
<h2> </h2>
<button
className="close-btn"
type="button"
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
alt="닫기"
/>
</button>
</div>
</div>
<div className="bottomsheet-content">
<div className="bottom-section">
<p> , . </p>
<ul className="list-style-circle">
<li> </li>
<li> </li>
</ul>
</div>
</div>
<div className="bottomsheet-footer">
<button
className="btn-50 btn-blue flex-1"
type="button"
></button>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,63 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
export const BottomSheetEmail = () => {
return (
<>
<div className="bg-dim"></div>
<div className="bottomsheet">
<div className="bottomsheet-header">
<div className="bottomsheet-title">
<h2> </h2>
<button
className="close-btn"
type="button"
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
alt="닫기"
/>
</button>
</div>
</div>
<div className="bottomsheet-content">
<div className="email-section">
<div className="email-label">
<div className="mail-icon">
<div className="mail-icon-bg"></div>
<img
src="../images/ico_email.svg"
alt="메일"
/>
</div>
<span className="label-text"> </span>
</div>
<div className="email-select">
<div className="select-wrapper">
<select>
<option></option>
<option>1</option>
<option>2</option>
</select>
</div>
</div>
<div className="error-message">
<p> .<br /> .</p>
</div>
</div>
</div>
<div className="bottomsheet-footer">
<button
className="btn-50 btn-blue flex-1"
type="button"
disabled
></button>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,90 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
export const CashReceitHandWrittenIssuanceStep1 = () => {
const { navigate } = useNavigate();
useSetOnBack(() => {
navigate(PATHS.transaction.cashReceit.list);
});
return (
<>
<h2 className="issue-title"> </h2>
<div className="issue-form">
<div className="issue-row">
<div className="issue-label"> </div>
<div className="issue-field">
<input
className="error"
type="text"
value="123456789"
disabled={ true }
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<div className="seg-buttons">
<button
className="btn-40 btn-blue"
type="button"
></button>
<button
className="btn-40 btn-white"
type="button"
></button>
</div>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder="상품명"
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder="구매자명"
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder="사업자번호 OR 휴대폰번호"
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"> </div>
<div className="issue-field">
<input
type="email"
placeholder="TEST123@nicepay.com"
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="tel"
placeholder="01012345678"
/>
</div>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,81 @@
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
import { ProcessStep } from '../model/types';
export interface CashReceitHandWrittenIssuanceStep2Props {
setProcessStep: ((processStep: ProcessStep) => void);
};
export const CashReceitHandWrittenIssuanceStep2 = ({
setProcessStep
}: CashReceitHandWrittenIssuanceStep2Props) => {
useSetOnBack(() => {
setProcessStep(ProcessStep.One);
});
return (
<>
<h2 className="issue-title"> </h2>
<div className="issue-form">
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<div className="seg-buttons">
<input
type="text"
value="555,555,555"
readOnly={ true }
/>
<button
className="btn-40 btn-white"
type="button"
>VAT자동계산</button>
</div>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
className="error"
type="text"
placeholder=""
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label">VAT</div>
<div className="issue-field">
<input
className="error"
type="text"
placeholder=""
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"></div>
<div className="issue-field">
<input
className="error"
type="text"
placeholder=""
/>
</div>
</div>
<div className="issue-row">
<div className="issue-label"> </div>
<div className="issue-field">
<input
type="email"
className="error"
placeholder=""
/>
</div>
</div>
<div className="issue-note error">
VAT,, .
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,44 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { CashReceitListProps } from '../model/types';
import { ListDateGroup } from './list-date-group';
export const CashReceitList = ({
pageType,
listItems
}: CashReceitListProps) => {
const { navigate } = useNavigate();
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
rs.push(
<ListDateGroup
pageType={ pageType }
key={ key }
date={ key }
items={ value }
></ListDateGroup>
);
}
return rs;
};
const onClickToNavigate = () => {
navigate(PATHS.transaction.cashReceit.handWrittenIssuance);
};
return (
<>
<div className="transaction-list">
{ getListDateGroup() }
<div className="apply-row bottom-padding">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
></button>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,122 @@
import { useEffect, useState } from 'react';
import { motion } from 'framer-motion';
import { NumericFormat } from 'react-number-format';
import { DetailInfoKeys, DetailInfoProps } from '../model/types';
import { DetailArrow } from './detail-arrow';
import { useDownloadConfirmationMutation } from '../api/use-download-confirmation-mutation';
export const DetailAmountInfo = ({
pageType,
amountInfo,
show,
tid,
onClickToShowInfo
}: DetailInfoProps) => {
const { mutateAsync: downloadConfirmation } = useDownloadConfirmationMutation();
const variants = {
hidden: { height: 0, padding: 0, margin: 0, display: 'none' },
visible: { height: 'auto', padding: '16px', margin: '10px 0', display: 'block' },
};
const onClickToSetShowInfo = () => {
if(!!onClickToShowInfo){
onClickToShowInfo(DetailInfoKeys.Amount);
}
};
const onClickToDownloadConfirmation = () => {
if(!!tid){
downloadConfirmation({
tid: tid
}).then((rs) => {
alert('거래확인서 다운 성공');
});
}
};
return (
<>
<div className="txn-num-group">
<div className="txn-amount">
<div className="value">
<NumericFormat
value={ amountInfo?.amount }
thousandSeparator
displayType="text"
></NumericFormat>
<span className="unit"></span>
</div>
<button
className="chip-btn"
type="button"
onClick={ () => onClickToSetShowInfo() }
>
<DetailArrow show={ show }></DetailArrow>
</button>
</div>
<motion.div
className="amount-expand"
initial="hidden"
animate={ (show)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
>
<ul className="amount-list">
<li className="amount-item">
<span className="label">·&nbsp;&nbsp;</span>
<span className="value">
<NumericFormat
value={ amountInfo?.cardAmount }
thousandSeparator
displayType="text"
></NumericFormat>
</span>
</li>
<li className="amount-item">
<span className="label">·&nbsp;&nbsp;</span>
<span className="value">
<NumericFormat
value={ amountInfo?.pointAmount }
thousandSeparator
displayType="text"
></NumericFormat>
</span>
</li>
<li className="amount-item">
<span className="label">·&nbsp;&nbsp;</span>
<span className="value minus">
<NumericFormat
value={ amountInfo?.couponAmount }
thousandSeparator
displayType="text"
></NumericFormat>
</span>
</li>
<li className="amount-item">
<span className="label">·&nbsp;&nbsp;</span>
<span className="value">
<NumericFormat
value={ amountInfo?.escrowFee }
thousandSeparator
displayType="text"
></NumericFormat>
</span>
</li>
</ul>
</motion.div>
<div className="txn-mid">
<span className="value">{ amountInfo?.mid }</span>
</div>
<div className="txn-doc">
<button
className="doc-btn"
type="button"
onClick={ () => onClickToDownloadConfirmation() }
> </button>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,23 @@
import { useEffect, useState } from 'react';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { AltMsgKeys, DetailArrowProps } from '../model/types';
export const DetailArrow = ({ show }: DetailArrowProps) => {
const [altMsg, setAltMsg] = useState<AltMsgKeys>(AltMsgKeys.Fold);
const [className, setClassName] = useState<string>('ic20 rot-180');
useEffect(() => {
setAltMsg((show)? AltMsgKeys.Fold: AltMsgKeys.UnFold);
setClassName(`ic20 ${(show)? 'rot-180': ''}`);
}, [show]);
return (
<>
<img
className={ className }
src={ IMAGE_ROOT + '/select_arrow.svg' }
alt={ altMsg }
/>
</>
);
};

View File

@@ -0,0 +1,52 @@
import { NumericFormat } from 'react-number-format';
import moment from 'moment';
import { DetailInfoProps } from '../model/types';
import { IMAGE_ROOT } from '@/shared/constants/common';
export const DetailImportantInfo = ({
pageType,
importantInfo
}: DetailInfoProps) => {
return (
<>
<div className="txn-section">
<div className="section-title"> </div>
<ul className="kv-list">
<li className="kv-row">
<span className="k"></span>
<span className="v">{ importantInfo?.ordNo }</span>
</li>
<li className="kv-row">
<span className="k">TID</span>
<span className="v">{ importantInfo?.tid }</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{ importantInfo?.tradeStatus }</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{ importantInfo?.tradeMethod }</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{ moment(importantInfo?.approvalDate).format('YYYY.MM.DD') }</span>
</li>
{
/*
<li className="kv-row">
<span className="k">취소일</span>
<span className="v">2025.06.08</span>
</li>
*/
}
<li className="kv-row">
<span className="k"></span>
<span className="v">{ importantInfo?.productName }</span>
</li>
</ul>
</div>
</>
)
};

View File

@@ -0,0 +1,79 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import { NumericFormat } from 'react-number-format';
import { DetailInfoKeys, DetailInfoProps } from '../model/types';
import { DetailArrow } from './detail-arrow';
export const DetailPartCancelInfo = ({
pageType,
partCancelInfo,
show,
onClickToShowInfo
}: DetailInfoProps) => {
const variants = {
hidden: { height: 0, padding: 0, display: 'none' },
visible: { height: 'auto', paddingTop: '12px', display: 'block' },
};
const onClickToSetShowInfo = () => {
if(!!onClickToShowInfo){
onClickToShowInfo(DetailInfoKeys.PartCancel);
}
};
return (
<>
<div className="txn-section">
<div
className="section-title with-toggle"
onClick={ () => onClickToSetShowInfo() }
>
<DetailArrow show={ show }></DetailArrow>
</div>
<motion.ul
className="kv-list"
initial="hidden"
animate={ (show)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
>
<li className="kv-row">
<span className="k"> TID</span>
<span className="v">{ partCancelInfo?.originalTid }</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="v">
<NumericFormat
value={ partCancelInfo?.originalAmount }
thousandSeparator
displayType="text"
suffix={ '원' }
></NumericFormat>
</span>
</li>
<li className="kv-row">
<span className="k"> TID</span>
<span className="v">nictest00m01012506171629294150</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="v">50,000</span>
</li>
<li className="kv-row nopadding">
<span className="k"> </span>
<span className="v">
<NumericFormat
value={ partCancelInfo?.remainingAmount }
thousandSeparator
displayType="text"
suffix={ '원' }
></NumericFormat>
</span>
</li>
</motion.ul>
</div>
</>
)
};

View File

@@ -0,0 +1,50 @@
import { motion } from 'framer-motion';
import { DetailInfoKeys, DetailInfoProps } from '../model/types';
import { DetailArrow } from './detail-arrow';
export const DetailPaymentInfo = ({
pageType,
paymentInfo,
show,
onClickToShowInfo
}: DetailInfoProps) => {
const variants = {
hidden: { height: 0, padding: 0, display: 'none' },
visible: { height: 'auto', paddingTop: '12px', display: 'block' },
};
const onClickToSetShowInfo = () => {
if(!!onClickToShowInfo){
onClickToShowInfo(DetailInfoKeys.Payment);
}
};
return (
<>
<div className="txn-section">
<div
className="section-title with-toggle"
onClick={ () => onClickToSetShowInfo() }
>
<DetailArrow show={ show }></DetailArrow>
</div>
<motion.ul
className="kv-list"
initial="hidden"
animate={ (show)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
>
<li className="kv-row">
<span className="k"> </span>
<span className="v">10,000,000</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">0</span>
</li>
</motion.ul>
</div>
</>
)
};

View File

@@ -0,0 +1,51 @@
import moment from 'moment';
import { motion } from 'framer-motion';
import { DetailInfoKeys, DetailInfoProps } from '../model/types';
import { DetailArrow } from './detail-arrow';
export const DetailSettlementInfo = ({
pageType,
settlementInfo,
show,
onClickToShowInfo
}: DetailInfoProps) => {
const variants = {
hidden: { height: 0, padding: 0, display: 'none' },
visible: { height: 'auto', paddingTop: '12px', display: 'block' },
};
const onClickToSetShowInfo = () => {
if(!!onClickToShowInfo){
onClickToShowInfo(DetailInfoKeys.Settlement);
}
};
return (
<>
<div className="txn-section">
<div
className="section-title with-toggle"
onClick={ () => onClickToSetShowInfo() }
>
<DetailArrow show={ show }></DetailArrow>
</div>
<motion.ul
className="kv-list"
initial="hidden"
animate={ (show)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
>
<li className="kv-row">
<span className="k"> </span>
<span className="v">{ moment(settlementInfo?.approvalSettleDate).format('YYYY.MM.DD') }</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="v"></span>
</li>
</motion.ul>
</div>
</>
)
};

View File

@@ -0,0 +1,50 @@
import { motion } from 'framer-motion';
import { DetailInfoKeys, DetailInfoProps } from '../model/types';
import { DetailArrow } from './detail-arrow';
export const DetailTransactionInfo = ({
pageType,
transactionInfo,
show,
onClickToShowInfo
}: DetailInfoProps) => {
const variants = {
hidden: { height: 0, padding: 0, display: 'none' },
visible: { height: 'auto', paddingTop: '12px', display: 'block' },
};
const onClickToSetShowInfo = () => {
if(!!onClickToShowInfo){
onClickToShowInfo(DetailInfoKeys.Transaction);
}
};
return (
<>
<div className="txn-section" onClick={ () => onClickToSetShowInfo() }>
<div
className="section-title with-toggle"
>
<DetailArrow show={ show }></DetailArrow>
</div>
<motion.ul
className="kv-list"
initial="hidden"
animate={ (show)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
>
<li className="kv-row">
<span className="k"></span>
<span className="v">NICE PAY</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">123-45-67890</span>
</li>
</motion.ul>
</div>
</>
)
};

View File

@@ -0,0 +1,31 @@
import { EscroListProps } from '../model/types';
import { ListDateGroup } from './list-date-group';
export const EscroList = ({
pageType,
listItems
}: EscroListProps) => {
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
rs.push(
<ListDateGroup
pageType={ pageType }
key={ key }
date={ key }
items={ value }
></ListDateGroup>
);
}
return rs;
};
return (
<>
<div className="transaction-list">
{ getListDateGroup() }
</div>
</>
);
};

View File

@@ -0,0 +1,187 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
import { FilterProps } from '../model/types';
import { motion } from 'framer-motion';
export const Filter = ({
filterOn,
setFilterOn
}: FilterProps) => {
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const onClickToClose = () => {
setFilterOn(false);
};
return (
<>
<motion.div
id="fullMenuModal"
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
>
<div className="full-menu-container">
<div className="full-menu-header">
<div className="full-menu-title center"></div>
<div className="full-menu-actions">
<button
id="closeFullMenu"
className="full-menu-close"
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
alt="닫기"
onClick={ () => onClickToClose() }
/>
</button>
</div>
</div>
<div className="option-list pb-120">
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select className="flex-1">
<option>nictest001m</option>
</select>
</div>
</div>
<div className="opt-field">
<div className="opt-label">/ID</div>
<div className="opt-controls">
<select className="w-110">
<option></option>
<option>ID</option>
</select>
<input
className="flex-1"
type="text"
placeholder=""
/>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag">1</span>
<span className="keyword-tag"></span>
</div>
<div className="range-row">
<div className="input-wrapper date">
<input
className="date-input"
type="text"
placeholder="날짜 선택"
value="2025.06.08"
readOnly={ true }
/>
<button
type="button"
className="date-btn"
>
<img
src={ IMAGE_ROOT + '/ico_date.svg' }
alt="날짜 선택"
/>
</button>
</div>
<span className="beetween">~</span>
<div className="input-wrapper date">
<input
className="date-input"
type="text"
placeholder="날짜 선택"
value="2025.06.08"
readOnly={ true }
/>
<button
type="button"
className="date-btn"
>
<img
src={ IMAGE_ROOT + '/ico_date.svg' }
alt="날짜 선택"
/>
</button>
</div>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
<span
className="keyword-tag"
style={{ visibility: 'hidden' }}
></span>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select className="flex-1">
<option></option>
</select>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<div className="input-wrapper ">
<input
type="text"
placeholder=""
/>
</div>
<span> ~ </span>
<div className="input-wrapper date">
<input
type="text"
placeholder=""
/>
</div>
</div>
</div>
</div>
<div className="apply-row">
<button className="btn-50 btn-blue flex-1"></button>
</div>
</div>
</motion.div>
</>
);
};

View File

@@ -0,0 +1,52 @@
import moment from 'moment';
import 'moment/dist/locale/ko';
import { ListDateGroupProps } from '../model/types';
import { ListItem } from './list-item';
export const ListDateGroup = ({
pageType,
date,
items
}: ListDateGroupProps) => {
moment.locale('ko');
const getStateDate = () => {
let stateDate = moment(date).format('YY.MM.DD(ddd)');
return stateDate;
};
const getListItem = () => {
let rs = [];
if(!!items && items.length>0){
for(let i=0;i<items.length;i++){
let key = 'ListItem-'+i;
rs.push(
<ListItem
pageType={ pageType }
key={ key }
tid={ items[i]?.tid }
mid={ items[i]?.mid }
stateDate={ items[i]?.stateDate }
stateCode={ items[i]?.stateCode }
stateName={ items[i]?.stateName }
installmentMonth={ items[i]?.installmentMonth }
serviceCode={ items[i]?.serviceCode }
serviceName={ items[i]?.serviceName }
serviceDetailName={ items[i]?.serviceDetailName }
goodsAmount={ items[i]?.goodsAmount }
></ListItem>
)
}
}
return rs;
};
return (
<>
<div className="date-group">
<div className="date-header">{ getStateDate() }</div>
{ getListItem() }
</div>
</>
);
};

View File

@@ -0,0 +1,124 @@
import { NumericFormat } from 'react-number-format';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { ListItemProps, PageType } from '../model/types';
export const ListItem = ({
pageType,
tid,
mid,
stateDate,
stateCode,
stateName,
installmentMonth,
serviceCode,
serviceName,
serviceDetailName,
goodsAmount
}: ListItemProps) => {
const { navigate } = useNavigate();
const getItemClass = () => {
let rs = '';
if(stateCode === '0'){
rs = '';
}
else if(stateCode === '1'){
rs = 'approved';
}
else if(stateCode === '2'){
rs = 'refund';
}
return rs;
};
const getDotClass = (str?: string) => {
let rs = '';
if(stateCode === '0'){
rs = '';
}
else if(stateCode === '1'){
rs = 'blue';
}
else if(stateCode === '2'){
rs = 'gray';
}
return rs;
};
const onClickToNavigate = () => {
if(pageType === PageType.AllTransaction){
navigate(PATHS.transaction.allTransaction.detail + tid, {
state: {
tid: tid
}
});
}
else if(pageType === PageType.CashReceit){
navigate(PATHS.transaction.cashReceit.detail + tid, {
state: {
tid: tid
}
});
}
else if(pageType === PageType.Escro){
navigate(PATHS.transaction.escro.detail + tid, {
state: {
tid: tid
}
});
}
else if(pageType === PageType.Billing){
navigate(PATHS.transaction.billing.detail + tid, {
state: {
tid: tid
}
});
}
else{
alert('pageType 이 존재하지 않습니다.');
}
};
const getTime = () => {
let time = stateDate?.substring(8, 12);
let timeStr = time?.substring(0, 2) + ':' + time?.substring(2, 4);
return timeStr;
};
return (
<>
<div
className={ `transaction-item ${getItemClass()}` }
onClick={ () => onClickToNavigate() }
>
<div className="transaction-status">
<div className={ `status-dot ${getDotClass()}`}></div>
</div>
<div className="transaction-content">
<div className="transaction-title">{ `${serviceName}(${serviceDetailName})` }</div>
<div className="transaction-details">
<span>{ stateName }</span>
<span className="separator">|</span>
<span>{ getTime() }</span>
<span className="separator">|</span>
<span>{ mid }</span>
{ (!!installmentMonth && parseInt(installmentMonth) > 1) &&
<>
<span className="separator">|</span>
<span>{ installmentMonth } </span>
</>
}
</div>
</div>
<div className="transaction-amount">
<NumericFormat
value={ goodsAmount }
thousandSeparator
displayType="text"
suffix={ '원' }
></NumericFormat>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,25 @@
import {
SortByKeys,
SortOptionsBoxProps
} from '../model/types';
export const SortOptionsBox = ({
sortBy,
onCliCkToSort
}: SortOptionsBoxProps) => {
return (
<>
<div className="sort-options">
<button
className={ `sort-btn ${(sortBy === SortByKeys.New)? 'active': ''}` }
onClick={ () => onCliCkToSort(SortByKeys.New) }
></button>
<span className="sort-divider">|</span>
<button
className={ `sort-btn ${(sortBy === SortByKeys.Amount)? 'active': ''}` }
onClick={ () => onCliCkToSort(SortByKeys.Amount) }
></button>
</div>
</>
);
};