Added a confirmation for the payment record

This commit is contained in:
Tiago Ribeiro
2024-01-03 10:33:37 +00:00
parent c9cac3539c
commit 06dc92fdaa

View File

@@ -68,10 +68,10 @@ const PaymentCreator = ({onClose, reload, showComission = false}: {onClose: () =
const price = corporate?.corporateInformation?.payment?.value || 0; const price = corporate?.corporateInformation?.payment?.value || 0;
const commission = corporate?.corporateInformation?.payment?.commission || 0; const commission = corporate?.corporateInformation?.payment?.commission || 0;
const currency = corporate?.corporateInformation?.payment?.currency || 'EUR'; const currency = corporate?.corporateInformation?.payment?.currency || "EUR";
const referralAgent = useMemo(() => { const referralAgent = useMemo(() => {
if(corporate?.corporateInformation?.referralAgent) { if (corporate?.corporateInformation?.referralAgent) {
return users.find((u) => u.id === corporate.corporateInformation.referralAgent); return users.find((u) => u.id === corporate.corporateInformation.referralAgent);
} }
@@ -137,15 +137,7 @@ const PaymentCreator = ({onClose, reload, showComission = false}: {onClose: () =
<div className="flex flex-col gap-3 w-full"> <div className="flex flex-col gap-3 w-full">
<label className="font-normal text-base text-mti-gray-dim">Price *</label> <label className="font-normal text-base text-mti-gray-dim">Price *</label>
<div className="w-full grid grid-cols-5 gap-2"> <div className="w-full grid grid-cols-5 gap-2">
<Input <Input name="paymentValue" onChange={() => {}} type="number" value={price} defaultValue={0} className="col-span-3" disabled />
name="paymentValue"
onChange={() => {}}
type="number"
value={price}
defaultValue={0}
className="col-span-3"
disabled
/>
<Select <Select
className="px-4 col-span-2 py-4 w-full text-sm font-normal placeholder:text-mti-gray-cool disabled:bg-mti-gray-platinum/40 disabled:text-mti-gray-dim disabled:cursor-not-allowed bg-white rounded-full border border-mti-gray-platinum focus:outline-none" className="px-4 col-span-2 py-4 w-full text-sm font-normal placeholder:text-mti-gray-cool disabled:bg-mti-gray-platinum/40 disabled:text-mti-gray-dim disabled:cursor-not-allowed bg-white rounded-full border border-mti-gray-platinum focus:outline-none"
options={CURRENCIES.map(({label, currency}) => ({value: currency, label}))} options={CURRENCIES.map(({label, currency}) => ({value: currency, label}))}
@@ -176,14 +168,7 @@ const PaymentCreator = ({onClose, reload, showComission = false}: {onClose: () =
<div className="flex gap-4 w-full"> <div className="flex gap-4 w-full">
<div className="flex flex-col w-full gap-3"> <div className="flex flex-col w-full gap-3">
<label className="font-normal text-base text-mti-gray-dim">Commission *</label> <label className="font-normal text-base text-mti-gray-dim">Commission *</label>
<Input <Input name="commission" onChange={() => {}} type="number" defaultValue={0} value={commission} disabled />
name="commission"
onChange={() => {}}
type="number"
defaultValue={0}
value={commission}
disabled
/>
</div> </div>
<div className="flex flex-col w-full gap-3"> <div className="flex flex-col w-full gap-3">
<label className="font-normal text-base text-mti-gray-dim">Commission Value*</label> <label className="font-normal text-base text-mti-gray-dim">Commission Value*</label>
@@ -240,34 +225,27 @@ const PaymentCreator = ({onClose, reload, showComission = false}: {onClose: () =
}; };
const IS_PAID_OPTIONS = [ const IS_PAID_OPTIONS = [
{ {
value: null, value: null,
label: 'All', label: "All",
}, { },
value: false, {
label: 'Unpaid', value: false,
}, { label: "Unpaid",
value: true, },
label: 'Paid', {
}, value: true,
label: "Paid",
},
]; ];
const CSV_WHITELISTED_KEYS = [ const CSV_WHITELISTED_KEYS = ["corporateId", "corporate", "date", "amount", "agent", "agentCommission", "agentValue", "isPaid"];
'corporateId',
'corporate',
'date',
'amount',
'agent',
'agentCommission',
'agentValue',
'isPaid',
];
interface SimpleCSVColumn { interface SimpleCSVColumn {
key: string, key: string;
label: string, label: string;
index: number, index: number;
}; }
export default function PaymentRecord() { export default function PaymentRecord() {
const [selectedCorporateUser, setSelectedCorporateUser] = useState<User>(); const [selectedCorporateUser, setSelectedCorporateUser] = useState<User>();
@@ -283,7 +261,7 @@ export default function PaymentRecord() {
const {users, reload: reloadUsers} = useUsers(); const {users, reload: reloadUsers} = useUsers();
const {payments: originalPayments, reload: reloadPayment} = usePayments(); const {payments: originalPayments, reload: reloadPayment} = usePayments();
const [startDate, setStartDate] = useState<Date | null>(moment("01/01/2023").toDate()); const [startDate, setStartDate] = useState<Date | null>(moment("01/01/2023").toDate());
const [endDate, setEndDate] = useState<Date | null>(moment().endOf('day').toDate()); const [endDate, setEndDate] = useState<Date | null>(moment().endOf("day").toDate());
const [paid, setPaid] = useState<Boolean | null>(IS_PAID_OPTIONS[0].value); const [paid, setPaid] = useState<Boolean | null>(IS_PAID_OPTIONS[0].value);
const reload = () => { const reload = () => {
reloadUsers(); reloadUsers();
@@ -331,8 +309,8 @@ export default function PaymentRecord() {
useEffect(() => { useEffect(() => {
setFilters((prev) => [ setFilters((prev) => [
...prev.filter((x) => x.id !== "paid"), ...prev.filter((x) => x.id !== "paid"),
...(typeof paid !== 'boolean' ? [] : [{id: "paid", filter: (p: Payment) => p.isPaid === paid}]), ...(typeof paid !== "boolean" ? [] : [{id: "paid", filter: (p: Payment) => p.isPaid === paid}]),
]) ]);
}, [paid]); }, [paid]);
const updatePayment = (payment: Payment, key: string, value: any) => { const updatePayment = (payment: Payment, key: string, value: any) => {
@@ -473,29 +451,29 @@ export default function PaymentRecord() {
}; };
const columHelperValue = (key: string, info: any) => { const columHelperValue = (key: string, info: any) => {
switch(key) { switch (key) {
case 'agentCommission': { case "agentCommission": {
const value = info.getValue(); const value = info.getValue();
return { value: `${value}%`}; return {value: `${value}%`};
} }
case 'agent': { case "agent": {
const user = users.find((x) => x.id === info.row.original.agent) as AgentUser; const user = users.find((x) => x.id === info.row.original.agent) as AgentUser;
return { return {
value: user?.name, value: user?.name,
user, user,
} };
} }
case 'agentValue': case "agentValue":
case 'amount': { case "amount": {
const value = info.getValue(); const value = info.getValue();
const numberValue = toFixedNumber(value, 2) const numberValue = toFixedNumber(value, 2);
return { value: numberValue } return {value: numberValue};
} }
case 'date': { case "date": {
const value = info.getValue(); const value = info.getValue();
return { value: moment(value).format("DD/MM/YYYY") }; return {value: moment(value).format("DD/MM/YYYY")};
} }
case 'corporate': { case "corporate": {
const specificValue = info.row.original.corporate; const specificValue = info.row.original.corporate;
const user = users.find((x) => x.id === specificValue) as CorporateUser; const user = users.find((x) => x.id === specificValue) as CorporateUser;
return { return {
@@ -503,28 +481,26 @@ export default function PaymentRecord() {
value: user?.corporateInformation.companyInformation.name || user?.name, value: user?.corporateInformation.companyInformation.name || user?.name,
}; };
} }
case 'currency': { case "currency": {
return { return {
value: info.row.original.currency, value: info.row.original.currency,
}; };
} }
case 'isPaid': case "isPaid":
case 'corporateId': case "corporateId":
default: { default: {
const value = info.getValue(); const value = info.getValue();
return { value }; return {value};
} }
} }
};
}
const defaultColumns = [ const defaultColumns = [
columnHelper.accessor("corporate", { columnHelper.accessor("corporate", {
header: "Corporate ID", header: "Corporate ID",
id: 'corporateId', id: "corporateId",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
return value; return value;
}, },
}), }),
@@ -532,7 +508,7 @@ export default function PaymentRecord() {
header: "Corporate", header: "Corporate",
id: "corporate", id: "corporate",
cell: (info) => { cell: (info) => {
const { user, value } = columHelperValue(info.column.id, info); const {user, value} = columHelperValue(info.column.id, info);
return ( return (
<div <div
className={clsx( className={clsx(
@@ -548,7 +524,7 @@ export default function PaymentRecord() {
header: "Date", header: "Date",
id: "date", id: "date",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
return <span>{value}</span>; return <span>{value}</span>;
}, },
}), }),
@@ -556,20 +532,22 @@ export default function PaymentRecord() {
header: "Amount", header: "Amount",
id: "amount", id: "amount",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
const currency = CURRENCIES.find((x) => x.currency === info.row.original.currency)?.label const currency = CURRENCIES.find((x) => x.currency === info.row.original.currency)?.label;
const finalValue = `${value} ${currency}`; const finalValue = `${value} ${currency}`;
return <span>{finalValue}</span>; return <span>{finalValue}</span>;
} },
}), }),
columnHelper.accessor("agent", { columnHelper.accessor("agent", {
header: "Country Manager", header: "Country Manager",
id: "agent", id: "agent",
cell: (info) => { cell: (info) => {
const { user, value } = columHelperValue(info.column.id, info); const {user, value} = columHelperValue(info.column.id, info);
return ( return (
<div <div
className={clsx("underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer")} className={clsx(
"underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer",
)}
onClick={() => setSelectedAgentUser(user)}> onClick={() => setSelectedAgentUser(user)}>
{value} {value}
</div> </div>
@@ -580,16 +558,16 @@ export default function PaymentRecord() {
header: "Commission", header: "Commission",
id: "agentCommission", id: "agentCommission",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
return <>{value}</> return <>{value}</>;
}, },
}), }),
columnHelper.accessor("agentValue", { columnHelper.accessor("agentValue", {
header: "Commission Value", header: "Commission Value",
id: "agentValue", id: "agentValue",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
const currency = CURRENCIES.find((x) => x.currency === info.row.original.currency)?.label const currency = CURRENCIES.find((x) => x.currency === info.row.original.currency)?.label;
const finalValue = `${value} ${currency}`; const finalValue = `${value} ${currency}`;
return <span>{finalValue}</span>; return <span>{finalValue}</span>;
}, },
@@ -598,11 +576,17 @@ export default function PaymentRecord() {
header: "Paid", header: "Paid",
id: "isPaid", id: "isPaid",
cell: (info) => { cell: (info) => {
const { value } = columHelperValue(info.column.id, info); const {value} = columHelperValue(info.column.id, info);
return ( return (
<Checkbox <Checkbox
isChecked={value} isChecked={value}
onChange={(e) => (user?.type !== "agent" ? updatePayment(info.row.original, "isPaid", e) : null)}> onChange={(e) =>
user?.type !== "agent" && !value
? confirm(`Are you sure you want to consider this payment paid?`)
? updatePayment(info.row.original, "isPaid", e)
: null
: null
}>
<span></span> <span></span>
</Checkbox> </Checkbox>
); );
@@ -633,8 +617,8 @@ export default function PaymentRecord() {
}); });
const getUserModal = () => { const getUserModal = () => {
if(user) { if (user) {
if(selectedCorporateUser) { if (selectedCorporateUser) {
return ( return (
<Modal isOpen={!!selectedCorporateUser} onClose={() => setSelectedCorporateUser(undefined)}> <Modal isOpen={!!selectedCorporateUser} onClose={() => setSelectedCorporateUser(undefined)}>
<> <>
@@ -656,7 +640,7 @@ export default function PaymentRecord() {
); );
} }
if(selectedAgentUser) { if (selectedAgentUser) {
return ( return (
<Modal isOpen={!!selectedAgentUser} onClose={() => setSelectedAgentUser(undefined)}> <Modal isOpen={!!selectedAgentUser} onClose={() => setSelectedAgentUser(undefined)}>
<> <>
@@ -679,52 +663,48 @@ export default function PaymentRecord() {
} }
return null; return null;
} };
const getCSVData = () => { const getCSVData = () => {
const columns = table.getHeaderGroups().reduce((accm: SimpleCSVColumn[], group: HeaderGroup<Payment>) => { const columns = table.getHeaderGroups().reduce((accm: SimpleCSVColumn[], group: HeaderGroup<Payment>) => {
const whitelistedColumns = group.headers.filter((header) => CSV_WHITELISTED_KEYS.includes(header.id)); const whitelistedColumns = group.headers.filter((header) => CSV_WHITELISTED_KEYS.includes(header.id));
const data = whitelistedColumns.map((data) => ({ const data = whitelistedColumns.map((data) => ({
key: data.column.columnDef.id, key: data.column.columnDef.id,
label: data.column.columnDef.header, label: data.column.columnDef.header,
})) as SimpleCSVColumn[]; })) as SimpleCSVColumn[];
return [ return [...accm, ...data];
...accm,
...data,
];
}, []); }, []);
const { rows } = table.getRowModel(); const {rows} = table.getRowModel();
const finalColumns = [ const finalColumns = [
...columns, ...columns,
{ {
key: 'currency', key: "currency",
label: 'Currency', label: "Currency",
}, },
]; ];
return { return {
columns: finalColumns, columns: finalColumns,
rows: rows.map((row) => { rows: rows.map((row) => {
return finalColumns.reduce((accm, { key }) => { return finalColumns.reduce((accm, {key}) => {
const { value } = columHelperValue(key, { const {value} = columHelperValue(key, {
row, row,
getValue: () => row.getValue(key), getValue: () => row.getValue(key),
}); });
return { return {
...accm, ...accm,
[key]: value, [key]: value,
}; };
}, {}); }, {});
}), }),
}; };
} };
const { rows: csvRows, columns: csvColumns } = getCSVData(); const {rows: csvRows, columns: csvColumns} = getCSVData();
return ( return (
<> <>
<Head> <Head>
@@ -753,10 +733,7 @@ export default function PaymentRecord() {
{(user.type === "developer" || user.type === "admin") && ( {(user.type === "developer" || user.type === "admin") && (
<div className="flex justify-end gap-2"> <div className="flex justify-end gap-2">
<Button className="max-w-[200px]" variant="outline"> <Button className="max-w-[200px]" variant="outline">
<CSVLink <CSVLink data={csvRows} headers={csvColumns} filename="payment-records.csv">
data={csvRows}
headers={csvColumns}
filename="payment-records.csv">
Download CSV Download CSV
</CSVLink> </CSVLink>
</Button> </Button>
@@ -841,7 +818,7 @@ export default function PaymentRecord() {
options={IS_PAID_OPTIONS} options={IS_PAID_OPTIONS}
value={IS_PAID_OPTIONS.find((e) => e.value === paid)} value={IS_PAID_OPTIONS.find((e) => e.value === paid)}
onChange={(value) => { onChange={(value) => {
if(value) { if (value) {
setPaid(value.value); setPaid(value.value);
} }
}} }}
@@ -876,16 +853,16 @@ export default function PaymentRecord() {
filterDate={(date: Date) => moment(date).isSameOrBefore(moment(new Date()))} filterDate={(date: Date) => moment(date).isSameOrBefore(moment(new Date()))}
onChange={([initialDate, finalDate]: [Date, Date]) => { onChange={([initialDate, finalDate]: [Date, Date]) => {
setStartDate(initialDate ?? moment("01/01/2023").toDate()); setStartDate(initialDate ?? moment("01/01/2023").toDate());
if(finalDate) { if (finalDate) {
// basicly selecting a final day works as if I'm selecting the first // basicly selecting a final day works as if I'm selecting the first
// minute of that day. this way it covers the whole day // minute of that day. this way it covers the whole day
setEndDate(moment(finalDate).endOf('day').toDate()); setEndDate(moment(finalDate).endOf("day").toDate());
return; return;
} }
setEndDate(null); setEndDate(null);
}} }}
/> />
</div> </div>
</div> </div>
<table className="rounded-xl bg-mti-purple-ultralight/40 w-full"> <table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
<thead> <thead>