You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GHHub/src/views/report/Index.jsx

404 lines
15 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 [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 evaluationScores = vendorScoresData.EvaluationScores ? vendorScoresData.EvaluationScores[0] : [];
const primaryData = vendorScoresData.EvaluationScores
? [comm.pick(vendorScoresData.EvaluationScores[0], ['Groups', 'PersonNum', 'AmountUSD', 'EvaluationScore', 'TPReviews', 'TPReviewRate', 'Complaints', 'ComplaintRate'])]
: [];
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 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 },
];
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,
},];
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),
},
];
const columns_month = [{ title: 'Date', dataIndex: 'VMonth', key: 'VMonth' }, ...columns_primary];
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 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 { 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 } },
});
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 },
},
fieldComProps: { dates: { picker: 'month', presets: false } },
}}
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>
<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>
<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>
<Col md={24} lg={24} xxl={16}>
<Divider orientation='center'>
<Typography.Title level={3} type='success'>
DMC Assessment Criteria
</Typography.Title>
</Divider>
<Table key={'cs'} dataSource={DMCData_customer_satisfaction} columns={columns_DMC_customer_satisfaction} pagination={false} bordered />
<br />
<Table key={'sl'} dataSource={DMCData_sopport_local} columns={columns_DMC_sopport_local} pagination={false} bordered />
<br />
<Table key={'p'} 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 (Index);