feature/IO-3182-Phone-Number-Consent - Checkpoint
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import { useMutation, useQuery } from "@apollo/client";
|
||||
import { Table, Switch, Input, Tooltip, Upload, Button } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import {
|
||||
GET_PHONE_NUMBER_CONSENTS,
|
||||
SET_PHONE_NUMBER_CONSENT,
|
||||
BULK_SET_PHONE_NUMBER_CONSENT
|
||||
} from "../../graphql/consent.queries.js";
|
||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import { phone } from "phone";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
const mapDispatchToProps = () => ({});
|
||||
|
||||
function PhoneNumberConsentList({ bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
const [search, setSearch] = useState("");
|
||||
const { loading, data } = useQuery(GET_PHONE_NUMBER_CONSENTS, {
|
||||
variables: { bodyshopid: bodyshop.id, search },
|
||||
fetchPolicy: "network-only"
|
||||
});
|
||||
const [setConsent] = useMutation(SET_PHONE_NUMBER_CONSENT);
|
||||
const [bulkSetConsent] = useMutation(BULK_SET_PHONE_NUMBER_CONSENT);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t("consent.phone_number"),
|
||||
dataIndex: "phone_number",
|
||||
render: (text) => <PhoneNumberFormatter>{text}</PhoneNumberFormatter>
|
||||
},
|
||||
{
|
||||
title: t("consent.status"),
|
||||
dataIndex: "consent_status",
|
||||
render: (status, record) => (
|
||||
<Tooltip title={record.history?.[0]?.reason || "No audit history"}>
|
||||
<Switch
|
||||
checked={status}
|
||||
onChange={(checked) =>
|
||||
setConsent({
|
||||
variables: {
|
||||
bodyshopid: bodyshop.id,
|
||||
phone_number: record.phone_number,
|
||||
consent_status: checked,
|
||||
reason: "Manual override in app",
|
||||
changed_by: "user" // Replace with actual user email from context
|
||||
},
|
||||
optimisticResponse: {
|
||||
insert_phone_number_consent_one: {
|
||||
__typename: "phone_number_consent",
|
||||
id: record.id,
|
||||
bodyshopid: bodyshop.id,
|
||||
phone_number: record.phone_number,
|
||||
consent_status: checked,
|
||||
created_at: record.created_at,
|
||||
updated_at: new Date().toISOString(),
|
||||
consent_updated_at: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: t("consent.updated_at"),
|
||||
dataIndex: "consent_updated_at",
|
||||
render: (text) => <TimeAgoFormatter>{text}</TimeAgoFormatter>
|
||||
}
|
||||
];
|
||||
|
||||
const handleBulkUpload = async (file) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
const text = e.target.result;
|
||||
const lines = text.split("\n").slice(1); // Skip header
|
||||
const objects = lines
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => {
|
||||
const [phone_number, consent_status] = line.split(",");
|
||||
return {
|
||||
bodyshopid: bodyshop.id,
|
||||
phone_number: phone(phone_number, "CA").phoneNumber.replace(/^\+1/, ""),
|
||||
consent_status: consent_status.trim().toLowerCase() === "true"
|
||||
};
|
||||
});
|
||||
|
||||
try {
|
||||
await bulkSetConsent({
|
||||
variables: { objects },
|
||||
context: { headers: { "x-reason": "System update via bulk upload", "x-changed-by": "system" } }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Bulk upload failed:", error);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input.Search
|
||||
placeholder={t("general.labels.search")}
|
||||
onSearch={(value) => setSearch(value)}
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Upload beforeUpload={handleBulkUpload} accept=".csv" showUploadList={false}>
|
||||
<Button icon={<UploadOutlined />}>{t("consent.bulk_upload")}</Button>
|
||||
</Upload>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data?.phone_number_consent}
|
||||
loading={loading}
|
||||
rowKey="id"
|
||||
style={{ marginTop: 16 }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PhoneNumberConsentList);
|
||||
Reference in New Issue
Block a user