refactor: Report

feature/price_manager
Lei OT 1 year ago
parent 6e66a31bb0
commit 5b30aec3e5

@ -85,7 +85,6 @@ const useFeedbackStore = create(
...initialState,
reset: () => set(initialState),
setState: (state) => set(state),
setLoading: (loading) => set({ loading }),
setFeedbackList: (feedbackList) => set({ feedbackList }),

@ -1,113 +1,69 @@
import { makeAutoObservable, runInAction } from "mobx";
import { fetchJSON, postForm } from "@/utils/request";
import { prepareUrl, isNotEmpty } from "@/utils/commons";
import { fetchJSON } from "@/utils/request";
import { HT_HOST } from "@/config";
import { json } from "react-router-dom";
import * as config from "@/config";
import dayjs from "dayjs";
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
class Report {
constructor(root) {
makeAutoObservable(this, { rootStore: false });
this.root = root;
}
const initialState = {
loading: false,
vendorScoresData: [], //地接统计数据集,合计数据,每月数据,地接考核分数
productScoresData: [], //产品体验分析 常用酒店分析, 导游接待情况
commendScoresData: [], //表扬情况, 投诉情况, 评建议
};
export const useReportStore = create(
devtools((set, get) => ({
...initialState,
reset: () => set(initialState),
vendorScoresData = []; //地接统计数据集,合计数据,每月数据,地接考核分数
productScoresData = []; //产品体验分析 常用酒店分析, 导游接待情况
commendScoresData = []; //表扬情况, 投诉情况, 评建议
setLoading: (loading) => set({ loading }),
setVendorScoresData: (vendorScoresData) => set({ vendorScoresData }),
setProductScoresData: (productScoresData) => set({ productScoresData }),
setCommendScoresData: (commendScoresData) => set({ commendScoresData }),
loading = false;
search_date_start = dayjs().month(0).startOf("month");
search_date_end = dayjs().month(11).endOf("month");
onDateRangeChange = dates => {
this.search_date_start = dates == null ? null : dates[0].startOf("month");
this.search_date_end = dates == null ? null : dates[1].endOf("month");
};
getHWVendorScores(VEI_SN, StartDate, EndDate) {
this.loading = true;
const fetchUrl = prepareUrl(HT_HOST +"/service-cusservice/PTGetHWVendorScores")
.append("VEI_SN", VEI_SN)
.append("StartDate", StartDate)
.append("EndDate", EndDate)
.append("StrDEI_SN", "(,-1,)")
.append("OrderType", "-1")
.append("GroupType", "-1")
.append("token", this.root.authStore.login.token)
.build();
return fetchJSON(fetchUrl).then(json => {
runInAction(() => {
this.loading = false;
if (json.errcode == 0) {
if (isNotEmpty(json)) {
this.vendorScoresData = json;
} else {
this.vendorScoresData = [];
}
} else {
throw new Error(json.errmsg + ": " + json.errcode);
}
});
});
}
getHWProductScores(VEI_SN, StartDate, EndDate) {
this.loading = true;
const fetchUrl = prepareUrl(HT_HOST +"/service-cusservice/PTGetHWProductScores")
.append("VEI_SN", VEI_SN)
.append("StartDate", StartDate)
.append("EndDate", EndDate)
.append("StrDEI_SN", "(,-1,)")
.append("OrderType", "-1")
.append("GroupType", "-1")
.append("token", this.root.authStore.login.token)
.build();
return fetchJSON(fetchUrl).then(json => {
runInAction(() => {
this.loading = false;
if (json.errcode == 0) {
if (isNotEmpty(json)) {
this.productScoresData = json;
} else {
this.productScoresData = [];
}
} else {
throw new Error(json.errmsg + ": " + json.errcode);
}
});
});
}
getHWCommendScores(VEI_SN, StartDate, EndDate) {
this.loading = true;
const fetchUrl = prepareUrl(HT_HOST +"/service-cusservice/PTGetHWCommendScores")
.append("VEI_SN", VEI_SN)
.append("StartDate", StartDate)
.append("EndDate", EndDate)
.append("StrDEI_SN", "(,-1,)")
.append("OrderType", "-1")
.append("GroupType", "-1")
.append("token", this.root.authStore.login.token)
.build();
return fetchJSON(fetchUrl).then(json => {
runInAction(() => {
this.loading = false;
if (json.errcode == 0) {
if (isNotEmpty(json)) {
this.commendScoresData = json;
} else {
this.commendScoresData = [];
}
} else {
throw new Error(json.errmsg + ": " + json.errcode);
}
});
});
}
}
export default Report;
async getHWVendorScores(VEI_SN, StartDate, EndDate) {
const { setLoading, setVendorScoresData } = get();
setLoading(true);
const searchParams = {
VEI_SN,
StartDate,
EndDate,
StrDEI_SN: '(,-1,)',
OrderType: '-1',
GroupType: '-1',
};
const { errcode, ...Result } = await fetchJSON(`${HT_HOST}/service-cusservice/PTGetHWVendorScores`, searchParams);
setVendorScoresData(errcode === 0 ? Result : {});
setLoading(false);
},
async getHWProductScores(VEI_SN, StartDate, EndDate) {
const { setLoading, setProductScoresData } = get();
setLoading(true);
const searchParams = {
VEI_SN,
StartDate,
EndDate,
StrDEI_SN: '(,-1,)',
OrderType: '-1',
GroupType: '-1',
};
const { errcode, ...Result } = await fetchJSON(`${HT_HOST}/service-cusservice/PTGetHWProductScores`, searchParams);
setProductScoresData(errcode === 0 ? Result : {});
setLoading(false);
},
async getHWCommendScores(VEI_SN, StartDate, EndDate) {
const { setLoading, setCommendScoresData } = get();
setLoading(true);
const searchParams = {
VEI_SN,
StartDate,
EndDate,
StrDEI_SN: '(,-1,)',
OrderType: '-1',
GroupType: '-1',
};
const { errcode, ...Result } = await fetchJSON(`${HT_HOST}/service-cusservice/PTGetHWCommendScores`, searchParams);
setCommendScoresData(errcode === 0 ? Result : {});
setLoading(false);
},
}))
);
export default useReportStore;

@ -2,14 +2,12 @@ import { makeAutoObservable } from "mobx";
import { Reservation } from "./Reservation";
import { Auth } from "./Auth";
import {Invoice} from "./Invoice";
import Report from "./Report";
class Root {
constructor() {
this.reservationStore = new Reservation(this);
this.authStore = new Auth(this);
this.invoiceStore = new Invoice(this);
this.reportStore = new Report(this);
makeAutoObservable(this);
}

@ -1,505 +1,402 @@
import { useEffect } from "react";
import { observer } from "mobx-react";
import { Row, Col, Space, Button, Table, Divider, Typography, DatePicker } from "antd";
import { useStore } from "@/stores/StoreContext.js";
import * as config from "@/config";
import * as comm from "@/utils/commons";
import { usePDF } from "react-to-pdf";
import { Row, Col, Space, Button, Table, Divider, Typography } from 'antd';
import * as comm from '@/utils/commons';
import { usePDF } from 'react-to-pdf';
import dayjs from 'dayjs';
import SearchForm from '@/components/SearchForm';
import useAuthStore from '@/stores/Auth';
import useReportStore from '@/stores/Report';
function Index() {
const { reportStore, authStore } = useStore();
const { search_date_start, search_date_end, vendorScoresData, productScoresData, commendScoresData } = reportStore;
const evaluationScores = vendorScoresData.EvaluationScores ? vendorScoresData.EvaluationScores[0] : [];
useEffect(() => {}, []);
const columns_month = [
{
title: "Date",
dataIndex: "VMonth",
key: "VMonth",
},
{
title: "Groups",
dataIndex: "Groups",
key: "Groups",
},
{
title: "Number of People",
dataIndex: "PersonNum",
key: "PersonNum",
},
{
title: "Transaction AmountUSD)",
dataIndex: "AmountUSD",
key: "AmountUSD",
render: value => comm.formatPrice(value),
},
{
title: "Evaluation Score",
dataIndex: "EvaluationScore",
key: "EvaluationScore",
},
{
title: "TP Reviews",
dataIndex: "TPReviews",
key: "TPReviews",
},
{
title: "TP Reviews Rate",
dataIndex: "TPReviewRate",
key: "TPReviewRate",
render: value => comm.formatPercent(value),
},
{
title: "Complaints",
dataIndex: "Complaints",
key: "Complaints",
},
{
title: "Complaint Rate",
dataIndex: "ComplaintRate",
key: "ComplaintRate",
render: value => comm.formatPercent(value),
},
];
const [travelAgencyId, ] = useAuthStore((state) => [state.loginUser.travelAgencyId]);
const [vendorScoresData, getHWVendorScores] = useReportStore((state) => [state.vendorScoresData, state.getHWVendorScores]);
const [productScoresData, getHWProductScores] = useReportStore((state) => [state.productScoresData, state.getHWProductScores]);
const [commendScoresData, getHWCommendScores] = useReportStore((state) => [state.commendScoresData, state.getHWCommendScores]);
const columns_guide = [
{
title: "Name",
dataIndex: "TGI2_Name",
key: "TGI2_Name",
},
{
title: "Average Scores",
dataIndex: "VAverage",
key: "VAverage",
},
{
title: "Group Numbers",
dataIndex: "ReceptionGroups",
key: "ReceptionGroups",
},
{
title: "TP Reviews",
dataIndex: "CommendNum",
key: "CommendNum",
},
{
title: "TP Review Rate",
dataIndex: "CommendRate",
key: "CommendRate",
render: value => comm.formatPercent(value),
},
{
title: "Complaints",
dataIndex: "Complaints",
key: "Complaints",
},
{
title: "Complaint Rate",
dataIndex: "ComplaintRate",
key: "ComplaintRate",
render: value => comm.formatPercent(value),
},
];
const evaluationScores = vendorScoresData.EvaluationScores ? vendorScoresData.EvaluationScores[0] : [];
const primaryData = vendorScoresData.EvaluationScores
? [comm.pick(vendorScoresData.EvaluationScores[0], ['Groups', 'PersonNum', 'AmountUSD', 'EvaluationScore', 'TPReviews', 'TPReviewRate', 'Complaints', 'ComplaintRate'])]
: [];
const columns_commend = [
{
title: "Reference Number",
dataIndex: "GRI_No",
key: "GRI_No",
},
{
title: "Tour Guides",
dataIndex: "ObjectName",
key: "ObjectName",
},
{
title: "Essential Comments",
dataIndex: "ECI_Content",
key: "ECI_Content",
},
];
const evaluationScoresData = [
{ category: 'DMC Services', item: 'Guide', value: evaluationScores.FRTGuide, note: evaluationScores.FRTText },
{ category: 'DMC Services', item: 'Driver & Vehicle', value: evaluationScores.FRTGriver },
{ category: 'DMC Services', item: 'Food Arrangement', value: evaluationScores.FRTMeal },
{ category: 'DMC Services', item: 'Activity', value: evaluationScores.FRTProduct },
{ category: 'Itinerary Arrangements', item: 'Hotel', value: evaluationScores.FRTHotel, },
{ category: 'Itinerary Arrangements', item: 'Travel Advisor’s Planning', value: evaluationScores.FRTAdvisor },
];
const columns_evaluation = [
{ title: 'Category', dataIndex: 'category', key: 'category',align: 'center', onCell: (_, index) => ({ rowSpan: index === 0 ? 4 : index === 4 ? 2 : 0 }) },
{ title: 'Item', dataIndex: 'item', key: 'item', align: 'center' },
{ title: 'Your Scores', dataIndex: 'value', key: 'value',align: 'center', },
{ title: 'Note', dataIndex: 'note', key: 'note',align: 'center', onCell: (_, index) => ({ rowSpan: index === 0 ? 7 : 0 })},
];
const { toPDF, targetRef } = usePDF({
method: "save",
filename: "GHH-Report.pdf",
page: { margin: "3", format: "letter" }, //margin: Margin.SMALL,
canvas: { mimeType: "image/jpeg", qualityRatio: 1 },
overrides: { pdf: { compress: true }, canvas: { useCORS: true } },
});
const columns_DMC_customer_satisfaction = [
{ title: 'Customer Satisfaction', dataIndex: 'item', key: 'item',align: 'center', },
{ title: '3 scores', dataIndex: 'stand_3', key: 'stand_3', align: 'center', onCell: (_, index) => ({ colSpan: (index === 2 || index===4) ? 3 : 1 }) },
{ title: '4 scores', dataIndex: 'stand_4', key: 'stand_4',align: 'center',onCell: (_, index) => ({ colSpan: (index === 2 || index===4) ? 0 : 1 }) },
{ title: '5 scores', dataIndex: 'stand_5', key: 'stand_5',align: 'center',onCell: (_, index) => ({ colSpan: (index === 2 || index===4) ? 0 : 1 }) },
{ title: 'Your Scores', dataIndex: 'value', key: 'value',align: 'center', },
{ title: 'Final Scores', dataIndex: 'final_score', key: 'final_score',align: 'center', onCell: (_, index) => ({ rowSpan: index === 0 ? 5 : 0 })},
{ title: 'Note', dataIndex: 'note', key: 'note',align: 'center', },
];
const DMCData_customer_satisfaction = [
{
item: 'TP review rating',
stand_3: '\\',
stand_4: '30%',
stand_5: '60%',
value: evaluationScores.TPReviewRating,
final_score: evaluationScores.AvgCusSatisfaction,
note: evaluationScores.AvgCusSatisfaction,
},
{
item: 'Post tour complaints',
stand_3: '1',
stand_4: '0',
stand_5: '0',
value: evaluationScores.PostTourComplaints,
// final_score: evaluationScores.AvgCusSatisfaction,
note: evaluationScores.PostTourComplaintsText,
},
{
item: 'Complaints resolved during the tour',
stand_3: '3',
// stand_4: '0',
// stand_5: '0',
value: evaluationScores.ComplaintsDuringTour,
note: evaluationScores.ComplaintsDuringTourText,
},
{ item: 'Customer photos', stand_3: '\\', stand_4: '30%', stand_5: '50%', value: evaluationScores.CustomerPhotoRate, note: evaluationScores.CustomerPhotoRateText },
{ item: 'Evaluation scores', stand_3: '4.5', value: evaluationScores.EvaluationFormScore, note: evaluationScores.EvaluationFormScoreText },
];
return (
<Space direction="vertical" style={{ width: "100%" }}>
<Typography.Title level={3}></Typography.Title>
<Row gutter={16}>
<Col md={24} lg={8} xxl={6}>
<Space direction="horizontal">
Select Date
<DatePicker.RangePicker
format={config.DATE_FORMAT_MONTH}
allowClear={true}
style={{ width: "100%" }}
defaultValue={[search_date_start, search_date_end]}
onChange={reportStore.onDateRangeChange}
allowEmpty={true}
picker="month"
/>
</Space>
</Col>
<Col md={24} lg={4} xxl={4}>
<Button
type="primary"
loading={reportStore.loading}
onClick={() => {
reportStore.getHWVendorScores(
authStore.login.travelAgencyId,
search_date_start == null ? null : search_date_start.format(config.DATE_FORMAT),
search_date_end == null ? null : search_date_end.format(config.DATE_FORMAT)
);
reportStore.getHWProductScores(
authStore.login.travelAgencyId,
search_date_start == null ? null : search_date_start.format(config.DATE_FORMAT),
search_date_end == null ? null : search_date_end.format(config.DATE_FORMAT)
);
reportStore.getHWCommendScores(
authStore.login.travelAgencyId,
search_date_start == null ? null : search_date_start.format(config.DATE_FORMAT),
search_date_end == null ? null : search_date_end.format(config.DATE_FORMAT)
);
}}>
Get Report
</Button>
</Col>
<Col md={24} lg={10} xxl={11}>
<Button onClick={() => toPDF()}>Download PDF</Button>
</Col>
</Row>
<Typography.Title level={3}></Typography.Title>
const columns_DMC_sopport_local = [
{ title: 'Operator Support & Local resources', dataIndex: 'item', key: 'item',align: 'center', },
{ title: '3 scores', dataIndex: 'stand_3', key: 'stand_3', align: 'center', },
{ title: '4 scores', dataIndex: 'stand_4', key: 'stand_4',align: 'center', },
{ title: '5 scores', dataIndex: 'stand_5', key: 'stand_5',align: 'center', },
{ title: 'Your Scores', dataIndex: 'value', key: 'value',align: 'center', },
{ title: 'Final Scores', dataIndex: 'final_score', key: 'final_score',align: 'center', onCell: (_, index) => ({ rowSpan: index === 0 ? 6 : 0 })},
{ title: 'Note', dataIndex: 'note', key: 'note',align: 'center', },
];
const DMCData_sopport_local = [
{
item: 'Response efficiency',
stand_3: '1d',
stand_4: '6hrs',
stand_5: '3hrs',
value: evaluationScores.ResponseEfficiency,
final_score: evaluationScores.AvgLocalResources,
note: evaluationScores.ResponseEfficiencyText,
},
{
item: 'Provide suggestions and alternatives',
stand_3: '\\',
stand_4: '√',
stand_5: '√',
value: evaluationScores.ProvideSuggestions,
// final_score: evaluationScores.AvgCusSatisfaction,
note: evaluationScores.ProvideSuggestionsText,
},
{
item: 'Provide local tourism information',
stand_3: '\\',
stand_4: '√',
stand_5: '√',
value: evaluationScores.ProvideLocalInfo,
note: evaluationScores.ProvideLocalInfoText,
},
{ item: 'Assist in developing exclusive products',
stand_3: '\\',
stand_4: '\\',
stand_5: '√', value: evaluationScores.ExclusiveProducts, note: evaluationScores.ExclusiveProductsText },
{ item: 'Dedicated tour guide team for AH',
stand_3: '\\',
stand_4: '√',
stand_5: '√', value: evaluationScores.DedicatedTourGuide, note: evaluationScores.DedicatedTourGuideText },
{ item: 'Partner hotels with contracted rate',
stand_3: '\\',
stand_4: '√',
stand_5: '√', value: evaluationScores.PartnerHotels, note: evaluationScores.PartnerHotelsText },
];
const columns_DMC_pricing = [
{ title: 'Pricing & Settlement 20%', dataIndex: 'item', key: 'item',align: 'center', },
{ title: '3 scores', dataIndex: 'stand_3', key: 'stand_3', align: 'center', },
{ title: '4 scores', dataIndex: 'stand_4', key: 'stand_4',align: 'center', },
{ title: '5 scores', dataIndex: 'stand_5', key: 'stand_5',align: 'center', },
{ title: 'Your Scores', dataIndex: 'value', key: 'value',align: 'center', },
{ title: 'Final Scores', dataIndex: 'final_score', key: 'final_score',align: 'center', onCell: (_, index) => ({ rowSpan: index === 0 ? 3 : 0 })},
{ title: 'Note', dataIndex: 'note', key: 'note',align: 'center', },
];
const DMCData_pricing = [
{
item: 'Quotation',
stand_3: 'Package',
stand_4: 'Day tours',
stand_5: 'Individual services',
value: evaluationScores.Quotation,
final_score: evaluationScores.AvgPricingAndSettlement,
note: evaluationScores.QuotationText,
},
{
item: 'Settlement',
stand_3: 'Prepayment',
stand_4: 'Monthly Prepayment',
stand_5: 'Monthly settlement after the tours',
value: evaluationScores.Settlement,
note: evaluationScores.SettlementText,
},
{
item: 'Cancellation policy',
stand_3: '30 days',
stand_4: '21 days',
stand_5: '1 day',
value: evaluationScores.CancellationPolicy,
note: evaluationScores.CancellationPolicyText,
},];
<Row ref={targetRef}>
<Col md={24} lg={24} xxl={16}>
<Divider orientation="center">
<Typography.Title level={3} type="success">Primary Data</Typography.Title>
</Divider>
<div className="ant-table-wrapper ant-spin-nested-loading css-1x2egda css-dev-only-do-not-override-1x2egda ">
<div className="ant-spin-container ant-table ant-table-bordered">
<div className="ant-table-container">
<div className="ant-table-content">
<table style={{ textAlign: "center" }}>
<thead className="ant-table-thead">
<tr>
<th scope="col">Groups</th>
<th scope="col">Number of People</th>
<th scope="col">Transaction Amount (USD)</th>
<th scope="col">Evaluation Score</th>
<th scope="col">TP Reviews</th>
<th scope="col">TP Reviews Rate</th>
<th scope="col">Complaints</th>
<th scope="col">Complaint Rate</th>
</tr>
</thead>
<tbody className="ant-table-tbody">
<tr className="ant-table-row ant-table-row-level-0">
<td>{evaluationScores.Groups}</td>
<td>{evaluationScores.PersonNum}</td>
<td>{comm.formatPrice(evaluationScores.AmountUSD)}</td>
<td>{evaluationScores.EvaluationScore}</td>
<td>{evaluationScores.TPReviews}</td>
<td>{comm.formatPercent(evaluationScores.TPReviewRate)}</td>
<td>{evaluationScores.Complaints}</td>
<td>{comm.formatPercent(evaluationScores.ComplaintRate)}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</Col>
const columns_primary = [
{
title: 'Groups',
dataIndex: 'Groups',
key: 'Groups',
},
{
title: 'Number of People',
dataIndex: 'PersonNum',
key: 'PersonNum',
},
{
title: 'Transaction AmountUSD)',
dataIndex: 'AmountUSD',
key: 'AmountUSD',
render: (value) => comm.formatPrice(value),
},
{
title: 'Evaluation Score',
dataIndex: 'EvaluationScore',
key: 'EvaluationScore',
},
{
title: 'TP Reviews',
dataIndex: 'TPReviews',
key: 'TPReviews',
},
{
title: 'TP Reviews Rate',
dataIndex: 'TPReviewRate',
key: 'TPReviewRate',
render: (value) => comm.formatPercent(value),
},
{
title: 'Complaints',
dataIndex: 'Complaints',
key: 'Complaints',
},
{
title: 'Complaint Rate',
dataIndex: 'ComplaintRate',
key: 'ComplaintRate',
render: (value) => comm.formatPercent(value),
},
];
<Col md={24} lg={24} xxl={16}>
<Divider orientation="center">
<Typography.Title level={3} type="success">Monthly Data</Typography.Title>
</Divider>
<Table dataSource={vendorScoresData.MonthlyData} columns={columns_month} pagination={false} bordered />
</Col>
const columns_month = [{ title: 'Date', dataIndex: 'VMonth', key: 'VMonth' }, ...columns_primary];
<Col md={24} lg={24} xxl={16}>
<Divider orientation="center">
<Typography.Title level={3} type="success">DMC Assessment Criteria</Typography.Title>
</Divider>
<div className="ant-table-wrapper ant-spin-nested-loading css-1x2egda css-dev-only-do-not-override-1x2egda">
<div className="ant-spin-container ant-table ant-table-bordered">
<div className="ant-table-container">
<div className="ant-table-content">
<table style={{ textAlign: "center" }}>
<thead className="ant-table-thead">
<tr>
<th scope="col">Customer Satisfaction</th>
<th scope="col">3 scores</th>
<th scope="col">4 scores</th>
<th scope="col">5 scores</th>
<th scope="col">Your Scores</th>
<th scope="col">Final Scores</th>
<th scope="col">Note</th>
</tr>
</thead>
<tbody className="ant-table-tbody">
<tr className="ant-table-row ant-table-row-level-0">
<td>TP review rating</td>
<td>\</td>
<td>30%</td>
<td>60%</td>
<td>{evaluationScores.TPReviewRating}</td>
<td rowSpan="5">{evaluationScores.AvgCusSatisfaction}</td>
<td>{evaluationScores.TPReviewRatingText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Post tour complaints</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>{evaluationScores.PostTourComplaints}</td>
<td>{evaluationScores.PostTourComplaintsText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Complaints resolved during the tour</td>
<td colSpan={3}>3</td>
<td>{evaluationScores.ComplaintsDuringTour}</td>
<td>{evaluationScores.ComplaintsDuringTourText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Customer photos</td>
<td>\</td>
<td>30%</td>
<td>50%</td>
<td>{evaluationScores.CustomerPhotoRate}</td>
<td>{evaluationScores.CustomerPhotoRateText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Evaluation scores</td>
<td colSpan={3}>4.5</td>
<td>{evaluationScores.EvaluationFormScore}</td>
<td>{evaluationScores.EvaluationFormScoreText}</td>
</tr>
</tbody>
</table>
<br />
<table style={{ textAlign: "center" }}>
<thead className="ant-table-thead">
<tr>
<th scope="col">Operator Support & Local resources</th>
<th scope="col">3 scores</th>
<th scope="col">4 scores</th>
<th scope="col">5 scores</th>
<th scope="col">Your Scores</th>
<th scope="col">Final Scores</th>
<th scope="col">Note</th>
</tr>
</thead>
<tbody className="ant-table-tbody">
<tr className="ant-table-row ant-table-row-level-0">
<td>Response efficiency</td>
<td>1d</td>
<td>6hrs</td>
<td>3hrs</td>
<td>{evaluationScores.ResponseEfficiency}</td>
<td rowSpan="6">{evaluationScores.AvgLocalResources}</td>
<td>{evaluationScores.ResponseEfficiencyText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Provide suggestions and alternatives</td>
<td>\</td>
<td></td>
<td></td>
<td>{evaluationScores.ProvideSuggestions}</td>
<td>{evaluationScores.ProvideSuggestionsText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Provide local tourism information</td>
<td>\</td>
<td></td>
<td></td>
<td>{evaluationScores.ProvideLocalInfo}</td>
<td>{evaluationScores.ProvideLocalInfoText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Assist in developing exclusive products</td>
<td>\</td>
<td>\</td>
<td></td>
<td>{evaluationScores.ExclusiveProducts}</td>
<td>{evaluationScores.ExclusiveProductsText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Dedicated tour guide team for AH</td>
<td>\</td>
<td></td>
<td></td>
<td>{evaluationScores.DedicatedTourGuide}</td>
<td>{evaluationScores.DedicatedTourGuideText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Partner hotels with contracted rate</td>
<td>\</td>
<td></td>
<td></td>
<td>{evaluationScores.PartnerHotels}</td>
<td>{evaluationScores.PartnerHotelsText}</td>
</tr>
</tbody>
</table>
<br />
<table style={{ textAlign: "center" }}>
<thead className="ant-table-thead">
<tr>
<th scope="col">Pricing & Settlement 20%</th>
<th scope="col">3 scores</th>
<th scope="col">4 scores</th>
<th scope="col">5 scores</th>
<th scope="col">Your Scores</th>
<th scope="col">Final Scores</th>
<th scope="col">Note</th>
</tr>
</thead>
<tbody className="ant-table-tbody">
<tr className="ant-table-row ant-table-row-level-0">
<td>Quotation</td>
<td>Package</td>
<td>Day tours</td>
<td>Individual services</td>
<td>{evaluationScores.Quotation}</td>
<td rowSpan="3">{evaluationScores.AvgPricingAndSettlement}</td>
<td>{evaluationScores.QuotationText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Settlement</td>
<td>Prepayment</td>
<td>Monthly Prepayment</td>
<td>Monthly settlement after the tours</td>
<td>{evaluationScores.Settlement}</td>
<td>{evaluationScores.SettlementText}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Cancellation policy</td>
<td>30 days</td>
<td>21 days</td>
<td>1 day</td>
<td>{evaluationScores.CancellationPolicy}</td>
<td>{evaluationScores.CancellationPolicyText}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<Divider orientation="right">
<Typography.Title level={3} type="danger">
Final Scores: {evaluationScores.FinalScores}
</Typography.Title>
</Divider>
<br />
<Typography>
<Typography.Title level={3} type="success">
Scoring Rules
</Typography.Title>
<Typography.Paragraph type="success">
<ol>
<li>The maximum score is 5</li>
<li>
The three categories are:
<ul>
<li>Customer satisfaction (40%)</li>
<li>Operator support & local resources (40%)</li>
<li>Pricing & settlement (20%)</li>
</ul>
</li>
<li>For each category, you can only get the corresponding score if you meet the standards of all items under the score.</li>
<li>The final score is the sum of the scores of each category multiplied by the proportion of the category.</li>
</ol>
</Typography.Paragraph>
</Typography>
const columns_guide = [
{
title: 'Name',
dataIndex: 'TGI2_Name',
key: 'TGI2_Name',
},
{
title: 'Average Scores',
dataIndex: 'VAverage',
key: 'VAverage',
},
{
title: 'Group Numbers',
dataIndex: 'ReceptionGroups',
key: 'ReceptionGroups',
},
{
title: 'TP Reviews',
dataIndex: 'CommendNum',
key: 'CommendNum',
},
{
title: 'TP Review Rate',
dataIndex: 'CommendRate',
key: 'CommendRate',
render: (value) => comm.formatPercent(value),
},
{
title: 'Complaints',
dataIndex: 'Complaints',
key: 'Complaints',
},
{
title: 'Complaint Rate',
dataIndex: 'ComplaintRate',
key: 'ComplaintRate',
render: (value) => comm.formatPercent(value),
},
];
<br />
<Divider orientation="center">
<Typography.Title level={3} type="success">Evaluation Scores</Typography.Title>
</Divider>
<div className="ant-table-wrapper ant-spin-nested-loading css-1x2egda css-dev-only-do-not-override-1x2egda ">
<div className="ant-spin-container ant-table ant-table-bordered">
<div className="ant-table-container">
<div className="ant-table-content">
<table style={{ textAlign: "center" }}>
<thead className="ant-table-thead">
<tr>
<th scope="col">Category</th>
<th scope="col">Item</th>
<th scope="col">Your Scores</th>
<th scope="col">Note</th>
</tr>
</thead>
<tbody className="ant-table-tbody">
<tr className="ant-table-row ant-table-row-level-0">
<td rowSpan="4">DMC Services</td>
<td>Guide</td>
<td>{evaluationScores.FRTGuide}</td>
<td rowSpan="7">{evaluationScores.FRTText}</td>
</tr>
const columns_commend = [
{
title: 'Reference Number',
dataIndex: 'GRI_No',
key: 'GRI_No',
},
{
title: 'Tour Guides',
dataIndex: 'ObjectName',
key: 'ObjectName',
},
{
title: 'Essential Comments',
dataIndex: 'ECI_Content',
key: 'ECI_Content',
},
];
<tr className="ant-table-row ant-table-row-level-0">
<td>Driver & Vehicle</td>
<td>{evaluationScores.FRTGriver}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Food Arrangement</td>
<td>{evaluationScores.FRTMeal}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Activity</td>
<td>{evaluationScores.FRTProduct}</td>
</tr>
const { toPDF, targetRef } = usePDF({
method: 'save',
filename: 'GHH-Report.pdf',
page: { margin: '3', format: 'letter' }, //margin: Margin.SMALL,
canvas: { mimeType: 'image/jpeg', qualityRatio: 1 },
overrides: { pdf: { compress: true }, canvas: { useCORS: true } },
});
<tr className="ant-table-row ant-table-row-level-0">
<td rowSpan="2">Itinerary Arrangements</td>
<td>Hotel</td>
<td>{evaluationScores.FRTHotel}</td>
</tr>
<tr className="ant-table-row ant-table-row-level-0">
<td>Travel Advisor&rsquo;s Planning</td>
<td>{evaluationScores.FRTAdvisor}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</Col>
<Col md={24} lg={24} xxl={16}>
<Divider orientation="center">
<Typography.Title level={3} type="success">Tour Guides Performence</Typography.Title>
</Divider>
<Table dataSource={productScoresData.GuideScores} columns={columns_guide} pagination={false} bordered />
return (
<Space direction='vertical' style={{ width: '100%' }}>
{/* <Typography.Title level={3}></Typography.Title> */}
<Row gutter={16}>
<Col md={24} lg={18} xxl={12}>
<SearchForm
initialValue={{
dates: [dayjs().startOf('year'), dayjs().endOf('year')],
}}
defaultValue={{
shows: ['dates'],
fieldProps: {
dates: { label: 'Select Date', col: 12 },
},
}}
confirmText={'Get Report'}
onSubmit={(err, formVal, filedsVal) => {
getHWVendorScores(travelAgencyId, formVal.startdate, formVal.enddate);
getHWProductScores(travelAgencyId, formVal.startdate, formVal.enddate);
getHWCommendScores(travelAgencyId, formVal.startdate, formVal.enddate);
}}
/>
</Col>
<Col md={24} lg={6} xxl={12}>
<Button onClick={() => toPDF()}>Download PDF</Button>
</Col>
</Row>
<Divider orientation="center">
<Typography.Title level={3} type="success">TP Reviews</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.CommendScores} columns={columns_commend} pagination={false} bordered />
<Row ref={targetRef}>
<Col md={24} lg={24} xxl={16}>
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Primary Data
</Typography.Title>
</Divider>
<Table dataSource={primaryData} columns={columns_primary} pagination={false} bordered />
</Col>
<Divider orientation="center">
<Typography.Title level={3} type="success">Complaints</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.ComplaintScores} columns={columns_commend} pagination={false} bordered />
<Col md={24} lg={24} xxl={16}>
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Monthly Data
</Typography.Title>
</Divider>
<Table dataSource={vendorScoresData.MonthlyData} columns={columns_month} pagination={false} bordered />
</Col>
<Divider orientation="center">
<Typography.Title level={3} type="success">Suggestions from Customers</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.CriticizeScores} columns={columns_commend} pagination={false} bordered />
</Col>
</Row>
</Space>
);
<Col md={24} lg={24} xxl={16}>
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
DMC Assessment Criteria
</Typography.Title>
</Divider>
<Table dataSource={DMCData_customer_satisfaction} columns={columns_DMC_customer_satisfaction} pagination={false} bordered />
<br />
<Table dataSource={DMCData_sopport_local} columns={columns_DMC_sopport_local} pagination={false} bordered />
<br />
<Table dataSource={DMCData_pricing} columns={columns_DMC_pricing} pagination={false} bordered />
<Divider orientation='right'>
<Typography.Title level={3} type='danger'>
Final Scores: {evaluationScores.FinalScores}
</Typography.Title>
</Divider>
<br />
<Typography>
<Typography.Title level={3} type='success'>
Scoring Rules
</Typography.Title>
<Typography.Paragraph type='success'>
<ol>
<li>The maximum score is 5</li>
<li>
The three categories are:
<ul>
<li>Customer satisfaction (40%)</li>
<li>Operator support & local resources (40%)</li>
<li>Pricing & settlement (20%)</li>
</ul>
</li>
<li>For each category, you can only get the corresponding score if you meet the standards of all items under the score.</li>
<li>The final score is the sum of the scores of each category multiplied by the proportion of the category.</li>
</ol>
</Typography.Paragraph>
</Typography>
<br />
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Evaluation Scores
</Typography.Title>
</Divider>
<Table dataSource={evaluationScoresData} columns={columns_evaluation} pagination={false} bordered />
</Col>
<Col md={24} lg={24} xxl={16}>
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Tour Guides Performence
</Typography.Title>
</Divider>
<Table dataSource={productScoresData.GuideScores} columns={columns_guide} pagination={false} bordered />
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
TP Reviews
</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.CommendScores} columns={columns_commend} pagination={false} bordered />
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Complaints
</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.ComplaintScores} columns={columns_commend} pagination={false} bordered />
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
Suggestions from Customers
</Typography.Title>
</Divider>
<Table dataSource={commendScoresData.CriticizeScores} columns={columns_commend} pagination={false} bordered />
</Col>
</Row>
</Space>
);
}
export default observer(Index);
export default (Index);

Loading…
Cancel
Save