update confirm ui
This commit is contained in:
parent
7619ee2ba9
commit
b4062b1a08
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
@ -70,7 +70,11 @@ body #root{
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.table-operation-render{
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.page-content-container {
|
||||
max-width: 90%;
|
||||
width: 1400px;
|
||||
|
@ -12,6 +12,7 @@ import {BillStatus} from "@/service/types.ts";
|
||||
type BillListProps = {
|
||||
type: 'query' | 'reconciliation';
|
||||
operationRender?: (record: BillModel) => React.ReactNode;
|
||||
operationRenderWidth?: number;
|
||||
onRowSelection?: (selectedRowKeys: (string | number)[]) => void;
|
||||
source?: RecordList<BillModel>;
|
||||
onPageChange: (pageIndex:number) => void;
|
||||
@ -30,7 +31,7 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
return t('bill.pay_status_pending')
|
||||
case 'PAID':
|
||||
return t('bill.pay_status_paid')
|
||||
case 'CANCELLED':
|
||||
case 'CANCELED':
|
||||
return t('bill.pay_status_canceled')
|
||||
default:
|
||||
return billStatus
|
||||
@ -58,7 +59,7 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
title: t('base.student_number'),
|
||||
dataIndex: 'student_number',
|
||||
width: 150,
|
||||
render: (value) => value ?? 'N/A'
|
||||
render: (value) => value?.length ?value: 'N/A'
|
||||
},
|
||||
{
|
||||
title: t('base.bill_number'),
|
||||
@ -87,6 +88,7 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
title: 'Email',
|
||||
dataIndex: 'student_email',
|
||||
width: 200,
|
||||
render: (value) => value?.length ?value: 'N/A'
|
||||
// render: (_, record) => (<div>{record.student_english_name}<br/>{record.student_chinese_name}</div>)
|
||||
},
|
||||
{
|
||||
@ -103,12 +105,13 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
title: t('bill.title_year'),
|
||||
dataIndex: 'intake_year',
|
||||
width: 120,
|
||||
render: (_, record) => (<div>{record.intake_year}/{record.intake_semester}</div>)
|
||||
},
|
||||
{
|
||||
title: t('bill.title_semester'),
|
||||
dataIndex: 'intake_semester',
|
||||
width: 120,
|
||||
},
|
||||
// {
|
||||
// title: t('bill.title_semester'),
|
||||
// dataIndex: 'intake_semester',
|
||||
// width: 120,
|
||||
// },
|
||||
{
|
||||
title: t('bill.title_bill_detail'),
|
||||
dataIndex: 'detail',
|
||||
@ -186,7 +189,7 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
title: t('bill.title_operate'),
|
||||
dataIndex: 'operate',
|
||||
fixed: 'right',
|
||||
width: props.type == 'reconciliation'?120:220,
|
||||
width: props.operationRenderWidth || (props.type == 'reconciliation'?120:220),
|
||||
render: (_, record) => props.operationRender?.(record),
|
||||
})
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
"cancel_success": "Successful cancel bill",
|
||||
"confirm": "Check",
|
||||
"confirm_batch": "Batch Confirm",
|
||||
"confirm_bill_type": "Confirm Bill",
|
||||
"confirm_confirm_title": "Confirm check the Bill?",
|
||||
"confirm_select_empty": "Require confirm bill data",
|
||||
"confirm_success": "Confirm success!",
|
||||
@ -32,7 +33,7 @@
|
||||
"paid": "Paid",
|
||||
"paid_confirm": "Please confirm the order status is set to paid",
|
||||
"pay_status": "Bill Status",
|
||||
"pay_status_canceled": "CANCELLED",
|
||||
"pay_status_canceled": "CANCELED",
|
||||
"pay_status_paid": "PAID",
|
||||
"pay_status_pending": "PENDING",
|
||||
"query_amount_current_page": "The total amount of current page",
|
||||
@ -40,16 +41,20 @@
|
||||
"reconciliation_status_pending": "UNCHECKED",
|
||||
"reconciliation_status_submitted": "CHECKED",
|
||||
"require_student_number": "Search Student Number",
|
||||
"sort_asc": "ASC",
|
||||
"sort_desc": "DESC",
|
||||
"title_actual_payment_amount": "Actually Paid",
|
||||
"title_amount": "Amount",
|
||||
"title_bill_detail": "Bill Detail",
|
||||
"title_bill_list": "Bill List",
|
||||
"title_bill_status": "Bill Status",
|
||||
"title_create_at": "Input Date",
|
||||
"title_department": "Department",
|
||||
"title_operate": "Operation",
|
||||
"title_paid_at": "Transaction Date",
|
||||
"title_pay_amount": "Pay Amount",
|
||||
"title_pay_method": "Pay Method",
|
||||
"title_pay_sort": "Sort By",
|
||||
"title_program_id": "Program ID",
|
||||
"title_program_name": "Program",
|
||||
"title_reconciliation_status": "Reconciliation",
|
||||
@ -57,11 +62,7 @@
|
||||
"title_service_charge": "Service Charge",
|
||||
"title_student_name": "Student Name",
|
||||
"title_student_name_en": "English Name",
|
||||
"title_year": "Year",
|
||||
"title_create_at":"Input Date",
|
||||
"title_pay_sort":"Sort By",
|
||||
"sort_desc":"DESC",
|
||||
"sort_asc":"ASC"
|
||||
"title_year": "Year"
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Go Back",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"cancel_success": "作废账单成功",
|
||||
"confirm": "对账",
|
||||
"confirm_batch": "批量对账",
|
||||
"confirm_bill_type": "确认账单",
|
||||
"confirm_confirm_title": "请确定对账此账单?",
|
||||
"confirm_select_empty": "对账账单为空",
|
||||
"confirm_success": "对账成功!",
|
||||
@ -40,16 +41,20 @@
|
||||
"reconciliation_status_pending": "未对账",
|
||||
"reconciliation_status_submitted": "已对账",
|
||||
"require_student_number": "请输入查询学号",
|
||||
"sort_asc": "升序",
|
||||
"sort_desc": "降序",
|
||||
"title_actual_payment_amount": "实付金额",
|
||||
"title_amount": "账单金额",
|
||||
"title_bill_detail": "账单详情",
|
||||
"title_bill_list": "账单列表",
|
||||
"title_bill_status": "账单状态",
|
||||
"title_create_at": "创建时间",
|
||||
"title_department": "学系",
|
||||
"title_operate": "操作",
|
||||
"title_paid_at": "支付时间",
|
||||
"title_pay_amount": "应付金额",
|
||||
"title_pay_method": "支付方式",
|
||||
"title_pay_sort": "排序方式",
|
||||
"title_program_id": "专业ID",
|
||||
"title_program_name": "就读专业",
|
||||
"title_reconciliation_status": "对账状态",
|
||||
@ -57,11 +62,7 @@
|
||||
"title_service_charge": "手续费",
|
||||
"title_student_name": "学生姓名",
|
||||
"title_student_name_en": "英文名称",
|
||||
"title_year": "学年",
|
||||
"title_create_at":"创建时间",
|
||||
"title_pay_sort":"排序方式",
|
||||
"sort_desc":"降序",
|
||||
"sort_asc":"升序"
|
||||
"title_year": "学年"
|
||||
},
|
||||
"error": {
|
||||
"go_back": "返回上一页",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"cancel_success": "作廢帳單成功",
|
||||
"confirm": "對帳",
|
||||
"confirm_batch": "批次對帳",
|
||||
"confirm_bill_type": "確認賬單",
|
||||
"confirm_confirm_title": "請確定對帳此帳單?",
|
||||
"confirm_select_empty": "對帳帳單為空",
|
||||
"confirm_success": "對帳成功!",
|
||||
@ -40,16 +41,20 @@
|
||||
"reconciliation_status_pending": "未對帳",
|
||||
"reconciliation_status_submitted": "已對帳",
|
||||
"require_student_number": "請輸入查詢學號",
|
||||
"sort_asc": "升序",
|
||||
"sort_desc": "降序",
|
||||
"title_actual_payment_amount": "實付金額",
|
||||
"title_amount": "帳單金額",
|
||||
"title_bill_detail": "帳單詳情",
|
||||
"title_bill_list": "帳單清單",
|
||||
"title_bill_status": "帳單狀態",
|
||||
"title_create_at": "創建時間",
|
||||
"title_department": "學系",
|
||||
"title_operate": "操作",
|
||||
"title_paid_at": "付款時間",
|
||||
"title_pay_amount": "應付金額",
|
||||
"title_pay_method": "付款方式",
|
||||
"title_pay_sort": "排序方式",
|
||||
"title_program_id": "專業ID",
|
||||
"title_program_name": "就讀專業",
|
||||
"title_reconciliation_status": "對帳狀態",
|
||||
@ -57,11 +62,7 @@
|
||||
"title_service_charge": "手續費",
|
||||
"title_student_name": "學生姓名",
|
||||
"title_student_name_en": "英文名稱",
|
||||
"title_year": "學年",
|
||||
"title_create_at":"創建時間",
|
||||
"title_pay_sort":"排序方式",
|
||||
"sort_desc":"降序",
|
||||
"sort_asc":"升序"
|
||||
"title_year": "學年"
|
||||
},
|
||||
"error": {
|
||||
"go_back": "返回上一頁",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Button, Modal, Notification, Popconfirm, Space, Toast} from "@douyinfe/semi-ui";
|
||||
import {Button, Modal, Notification, Popconfirm, Space, Tag, Toast} from "@douyinfe/semi-ui";
|
||||
import {useState} from "react";
|
||||
import {useRequest, useSetState} from "ahooks";
|
||||
import {useTranslation} from "react-i18next";
|
||||
@ -11,13 +11,13 @@ import {BillStatus, BizError} from "@/service/types.ts";
|
||||
import {useDownloadReceiptPDF} from "@/service/generate-pdf.ts";
|
||||
import useAuth from "@/hooks/useAuth.ts";
|
||||
import {BillDetailItems} from "@/components/bill";
|
||||
import MoneyFormat from "@/components/money-format.tsx";
|
||||
|
||||
|
||||
const DownloadButton = ({bill,text}: { bill: BillModel;text:string }) => {
|
||||
const {loading: downloading, downloadPDF} = useDownloadReceiptPDF()
|
||||
return (<Button
|
||||
onClick={() => downloadPDF(bill)} size={'small'} theme={'solid'}
|
||||
type={'primary'} loading={downloading}>{text}</Button>)
|
||||
const DownloadButton = ({bill, text}: { bill: BillModel; text: string }) => {
|
||||
const {loading: downloading, downloadPDF} = useDownloadReceiptPDF()
|
||||
return (<Button
|
||||
onClick={() => downloadPDF(bill)} size={'small'} loading={downloading}>{text}</Button>)
|
||||
}
|
||||
|
||||
// const ConfirmPaidBill =({bill,onRefresh}: { bill: BillModel;onRefresh:()=>void }) => {
|
||||
@ -25,63 +25,66 @@ const DownloadButton = ({bill,text}: { bill: BillModel;text:string }) => {
|
||||
// }
|
||||
|
||||
const BillQuery = () => {
|
||||
const {user} = useAuth();
|
||||
const [state,setState] = useSetState<{
|
||||
updateBill?: BillModel
|
||||
updateLoading?:boolean
|
||||
}>({})
|
||||
const [showBill, setShowBill] = useState<BillModel>()
|
||||
const [queryParams, setBillQueryParams] = useState<BillQueryParams>({});
|
||||
const {data, loading, refresh} = useRequest(() => billList({
|
||||
...queryParams,
|
||||
department: user?.department == 'RO' ? 'RO' : 'FO',
|
||||
}), {
|
||||
refreshDeps: [queryParams],
|
||||
onError: (e) => {
|
||||
Notification.error({title: 'Error', content: e.message})
|
||||
}
|
||||
})
|
||||
const {t} = useTranslation()
|
||||
const {user} = useAuth();
|
||||
const [state, setState] = useSetState<{
|
||||
updateBill?: BillModel
|
||||
updateLoading?: boolean
|
||||
confirmBill?: BillModel
|
||||
}>({})
|
||||
const [showBill, setShowBill] = useState<BillModel>()
|
||||
const [queryParams, setBillQueryParams] = useState<BillQueryParams>({});
|
||||
const {data, loading, refresh} = useRequest(() => billList({
|
||||
...queryParams,
|
||||
department: user?.department == 'RO' ? 'RO' : 'FO',
|
||||
}), {
|
||||
refreshDeps: [queryParams],
|
||||
onError: (e) => {
|
||||
Notification.error({title: 'Error', content: e.message})
|
||||
}
|
||||
})
|
||||
const {t} = useTranslation()
|
||||
|
||||
const onConfirmCancel = (bill: BillModel) => {
|
||||
modifyBillStatus(bill.id,'CANCELLED').then(() => {
|
||||
Notification.success({title: 'Notice', content: t('bill.cancel_success')})
|
||||
refresh()
|
||||
}).catch((e:BizError) => {
|
||||
Toast.error({
|
||||
content: `${t('base.operate_fail')}:${e.message}`,
|
||||
duration: 3
|
||||
})
|
||||
})
|
||||
}
|
||||
const onConfirmCancel = (bill: BillModel) => {
|
||||
modifyBillStatus(bill.id, 'CANCELLED').then(() => {
|
||||
Notification.success({title: 'Notice', content: t('bill.cancel_success')})
|
||||
refresh()
|
||||
}).catch((e: BizError) => {
|
||||
Toast.error({
|
||||
content: `${t('base.operate_fail')}:${e.message}`,
|
||||
duration: 3
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const onConfirmPaid = () => {
|
||||
if(!state.updateBill) return;
|
||||
setState({
|
||||
updateLoading: true
|
||||
})
|
||||
modifyBillStatus(state.updateBill.id,'PAID').then(() => {
|
||||
setState({
|
||||
updateBill: undefined,updateLoading: false
|
||||
})
|
||||
Notification.success({title: 'Notice', content: t('base.operate_success')})
|
||||
refresh()
|
||||
}).catch((e:BizError) => {
|
||||
const onConfirmPaid = () => {
|
||||
if (!state.updateBill) return;
|
||||
setState({
|
||||
updateLoading: true
|
||||
})
|
||||
modifyBillStatus(state.updateBill.id, 'PAID').then(() => {
|
||||
setState({
|
||||
updateBill: undefined, updateLoading: false
|
||||
})
|
||||
Notification.success({title: 'Notice', content: t('base.operate_success')})
|
||||
refresh()
|
||||
}).catch((e: BizError) => {
|
||||
setState({
|
||||
updateLoading: false
|
||||
})
|
||||
Toast.error({
|
||||
content: `${t('base.operate_fail')}:${e.message}`,
|
||||
duration: 3
|
||||
})
|
||||
})
|
||||
}
|
||||
const operation = (bill: BillModel) => {
|
||||
Toast.error({
|
||||
content: `${t('base.operate_fail')}:${e.message}`,
|
||||
duration: 3
|
||||
})
|
||||
})
|
||||
}
|
||||
const operation = (bill: BillModel) => {
|
||||
|
||||
return (<Space>
|
||||
{bill.status != BillStatus.PAID && <Button onClick={()=>setState({updateBill:bill})} size={'small'} theme={'solid'} type={'danger'}>{t('bill.paid')}</Button>
|
||||
}
|
||||
{bill.status == BillStatus.PENDING && <>
|
||||
return (<div className={'table-operation-render'}>
|
||||
{bill.status != BillStatus.PAID &&
|
||||
<Button onClick={() => setState({updateBill: bill})} size={'small'} theme={'solid'}
|
||||
type={'danger'}>{t('bill.paid')}</Button>
|
||||
}
|
||||
{bill.status == BillStatus.PENDING && <>
|
||||
<Popconfirm
|
||||
title={'Notice'}
|
||||
content={`${t('bill.cancel_confirm')}?`}
|
||||
@ -92,51 +95,86 @@ const BillQuery = () => {
|
||||
</Popconfirm>
|
||||
<Button onClick={() => setShowBill(bill)} size={'small'} theme={'solid'}
|
||||
type={'primary'}>{t('base.qr-code')}</Button>
|
||||
{AppMode == 'development' && <a href={`/pay?bill=${bill.id}`} target={'_blank'}>支付</a>}
|
||||
{AppMode == 'development' && <a href={`/pay?bill=${bill.id}`} target={'_blank'}>支付</a>}
|
||||
</>}
|
||||
{
|
||||
bill.status == BillStatus.PAID && <DownloadButton bill={bill} text={t('bill.download_receipt')}/>
|
||||
}
|
||||
</Space>)
|
||||
}
|
||||
return (<div>
|
||||
<SearchForm showApply loading={loading} onSearch={setBillQueryParams}/>
|
||||
<BillList
|
||||
type={'query'} loading={loading}
|
||||
operationRender={operation} source={data}
|
||||
onPageChange={(page_number) => {
|
||||
setBillQueryParams({
|
||||
...queryParams,
|
||||
page_number
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
title="Bill Detail"
|
||||
visible={!!showBill}
|
||||
width={620}
|
||||
onCancel={() => setShowBill(undefined)} //>=1.16.0
|
||||
closeOnEsc={true}
|
||||
footer={null}
|
||||
closeIcon={<span></span>}
|
||||
>
|
||||
{showBill && <BillDetail bill={showBill} onCancel={() => setShowBill(undefined)}/>}
|
||||
</Modal>
|
||||
<Modal
|
||||
title="Notice"
|
||||
visible={!!state.updateBill}
|
||||
closeOnEsc={true}
|
||||
onCancel={()=>{
|
||||
setState({updateBill:undefined,updateLoading:false})
|
||||
}}
|
||||
confirmLoading={state.updateLoading}
|
||||
onOk={onConfirmPaid}
|
||||
okText={t('base.confirm_paid')}
|
||||
maskClosable={false}
|
||||
>
|
||||
{state.updateBill && <div><BillDetailItems bill={state.updateBill} /></div>}
|
||||
<p style={{marginTop:10}}>{t('bill.paid_confirm')}</p>
|
||||
</Modal>
|
||||
</div>)
|
||||
{
|
||||
bill.status == BillStatus.PAID && <>
|
||||
<DownloadButton bill={bill} text={t('bill.download_receipt')}/>
|
||||
<Button onClick={() => setState({confirmBill: bill})}
|
||||
size={'small'} theme={'solid'}
|
||||
type={'primary'}>{t('bill.confirm_bill_type')}</Button>
|
||||
</>
|
||||
}
|
||||
</div>)
|
||||
}
|
||||
return (<div>
|
||||
<SearchForm showApply loading={loading} onSearch={setBillQueryParams}/>
|
||||
<BillList
|
||||
type={'query'} loading={loading} source={data}
|
||||
operationRender={operation} operationRenderWidth={180}
|
||||
onPageChange={(page_number) => {
|
||||
setBillQueryParams({
|
||||
...queryParams,
|
||||
page_number
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
title="Bill Detail"
|
||||
visible={!!showBill}
|
||||
width={620}
|
||||
onCancel={() => setShowBill(undefined)} //>=1.16.0
|
||||
closeOnEsc={true}
|
||||
footer={null}
|
||||
closeIcon={<span></span>}
|
||||
>
|
||||
{showBill && <BillDetail bill={showBill} onCancel={() => setShowBill(undefined)}/>}
|
||||
</Modal>
|
||||
<Modal
|
||||
title="Notice"
|
||||
visible={!!state.updateBill}
|
||||
closeOnEsc={true}
|
||||
onCancel={() => {
|
||||
setState({updateBill: undefined, updateLoading: false})
|
||||
}}
|
||||
confirmLoading={state.updateLoading}
|
||||
onOk={onConfirmPaid}
|
||||
okText={t('base.confirm_paid')}
|
||||
maskClosable={false}
|
||||
>
|
||||
{state.updateBill && <div><BillDetailItems bill={state.updateBill}/></div>}
|
||||
<p style={{marginTop: 10}}>{t('bill.paid_confirm')}</p>
|
||||
</Modal>
|
||||
<Modal
|
||||
title="Confirm Bill Type"
|
||||
visible={!!state.confirmBill}
|
||||
closeOnEsc={true}
|
||||
onCancel={() => {
|
||||
setState({confirmBill: undefined})
|
||||
}}
|
||||
footer={null}
|
||||
>
|
||||
{state.confirmBill && <>
|
||||
<div><BillDetailItems bill={state.confirmBill}/></div>
|
||||
<div className="confirm-container" style={{padding:'15px 0'}}>
|
||||
{
|
||||
state.confirmBill.details.map((it, idx) => (<div key={idx} className="confirm-item align-center space-between">
|
||||
<Space spacing={10}>
|
||||
<span>{it.id}.</span>
|
||||
<span>{it.bill_type}</span>
|
||||
<div>
|
||||
<MoneyFormat money={it.amount}/>
|
||||
</div>
|
||||
</Space>
|
||||
<div className="confirm-item-btn">
|
||||
{!!it.confirm_status ? <Tag color='light-blue'>CONFIRMED</Tag>:<Button>{t('base.confirm')}</Button>}
|
||||
|
||||
</div>
|
||||
</div>))
|
||||
}
|
||||
</div>
|
||||
</>}
|
||||
</Modal>
|
||||
</div>)
|
||||
}
|
||||
export default BillQuery
|
1
src/types/bill.d.ts
vendored
1
src/types/bill.d.ts
vendored
@ -12,6 +12,7 @@ declare type BillDetail = {
|
||||
id: string | number;
|
||||
bill_id: string | number;
|
||||
bill_type: string;
|
||||
confirm_status?: number;
|
||||
amount: decimal;
|
||||
}
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user