(companies): add bulk update for monitoring team assignment

dilmurod
Dilmurod 6 months ago
parent a76622cecb
commit 864387b0bc

@ -38,6 +38,13 @@ export interface UpdateTeamMonitorVars {
}; };
} }
export interface UpdateTeamMonitorCompaniesVars {
id: string;
payload: {
company_ids: number[];
};
}
export const teamController = { export const teamController = {
async read(obj: TTeamGetParams) { async read(obj: TTeamGetParams) {
const params = { ...obj }; const params = { ...obj };
@ -148,4 +155,25 @@ export const teamController = {
throw new Error("Failed to update team monitor"); throw new Error("Failed to update team monitor");
} }
}, },
async updateTeamMonitorCompanies(
id: string,
payload: { company_ids: number[] },
) {
try {
const { data } = await instance.put(
`/team-monitor/${id}/companies/`,
payload,
);
return data;
} catch (error: any) {
const errorMessage =
error?.response?.data?.message ||
error?.response?.data?.detail ||
"Something went wrong";
message.error(errorMessage);
throw error;
}
},
}; };

@ -0,0 +1,80 @@
import { Modal, Form, Select, message } from "antd";
import {
useTeamsMonitorData,
useUpdateTeamMonitorCompanies,
} from "../../Hooks/Teams";
interface Props {
open: boolean;
selectedIds: number[];
onCancel: () => void;
refetch: any;
}
const BulkEditModal = ({ open, selectedIds, onCancel, refetch }: Props) => {
const [form] = Form.useForm();
const { data, isLoading: teamsLoading } = useTeamsMonitorData({});
const updateMutation = useUpdateTeamMonitorCompanies();
const handleSubmit = async () => {
try {
const values = await form.validateFields();
await updateMutation.mutateAsync({
id: String(values.monitoringTeamId),
payload: {
company_ids: selectedIds,
},
});
message.success("Monitoring team updated successfully");
form.resetFields();
refetch();
onCancel();
} catch (error: any) {
console.log(error?.message || error || "Something went wrong");
}
};
return (
<Modal
title={`Monitoring Team Bulk Edit (${selectedIds.length})`}
open={open}
onCancel={onCancel}
onOk={handleSubmit}
okText="Save"
confirmLoading={updateMutation.isLoading}
okButtonProps={{
disabled: updateMutation.isLoading || selectedIds.length === 0,
}}
destroyOnClose
>
<Form layout="vertical" form={form}>
<Form.Item
label="Monitoring Team"
name="monitoringTeamId"
rules={[
{ required: true, message: "Please select a monitoring team" },
]}
>
<Select
placeholder="Select monitoring team"
allowClear
loading={teamsLoading}
showSearch
optionFilterProp="label"
disabled={updateMutation.isLoading}
options={data?.map((team: any) => ({
value: team.id,
label: team.name,
}))}
/>
</Form.Item>
</Form>
</Modal>
);
};
export default BulkEditModal;

@ -79,14 +79,6 @@ const Company = () => {
<div className="header d-flex"> <div className="header d-flex">
<Typography className="title">Companies</Typography> <Typography className="title">Companies</Typography>
{role !== "Checker" && ( {role !== "Checker" && (
// <button
// style={{ marginRight: 0 }}
// className="btn-add d-flex"
// onClick={showModal}
// >
// <img src={addicon} style={{ marginRight: 8 }} alt="" />
// Add Company
// </button>
<Button <Button
style={{ style={{
marginRight: 0, marginRight: 0,
@ -103,18 +95,8 @@ const Company = () => {
)} )}
</div> </div>
<div className="filter d-flex"> <div className="filter d-flex">
{/* <div className="search-div">
<img src={IconSearch} alt="" />
<input
className={`search-input-${themes}`}
type="text"
placeholder="Search"
onChange={handleSearchChange}
/>
</div> */}
<div> <div>
<Input <Input
// className={`search-input-${themes}`}
placeholder="Search" placeholder="Search"
prefix={<SearchOutlined />} prefix={<SearchOutlined />}
onChange={handleSearchChange} onChange={handleSearchChange}
@ -122,7 +104,7 @@ const Company = () => {
</div> </div>
</div> </div>
<CompanyTable data={data?.data} isLoading={isLoading} /> <CompanyTable data={data?.data} isLoading={isLoading} refetch={refetch} />
<Space style={{ width: "100%", marginTop: 40 }} direction="vertical"> <Space style={{ width: "100%", marginTop: 40 }} direction="vertical">
<Space <Space
style={{ style={{

@ -1,34 +1,43 @@
import React, { useState } from "react"; import { Button, Space, Table, Tooltip } from "antd";
import { Button, Space, Table, Tooltip, message } from "antd"; import { useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { SyncOutlined, EyeOutlined } from "@ant-design/icons"; import { EyeOutlined } from "@ant-design/icons";
import { companyController } from "../../API/LayoutApi/companies";
import { TCompany } from "../../types/Company/TCompany"; import { TCompany } from "../../types/Company/TCompany";
// @ts-ignore
import BulkEditModal from "./BulkEditModal";
import zippy from "../../assets/zippyicon.svg"; import zippy from "../../assets/zippyicon.svg";
// @ts-ignore
import evo from "../../assets/evoicon.png"; import evo from "../../assets/evoicon.png";
// @ts-ignore
import zeelog from "../../assets/zeelogicon.svg"; import zeelog from "../../assets/zeelogicon.svg";
// @ts-ignore
import ontime from "../../assets/ontimeicon.svg"; import ontime from "../../assets/ontimeicon.svg";
// @ts-ignore
import tt from "../../assets/tticon.svg"; import tt from "../../assets/tticon.svg";
// @ts-ignore
import tagIcon from "../../assets/tagIcon.svg"; import tagIcon from "../../assets/tagIcon.svg";
import { role } from "../../App"; import { role } from "../../App";
import { theme } from "antd";
function CompanyTable({ function CompanyTable({
data, data,
isLoading, isLoading,
refetch,
}: { }: {
data?: TCompany[] | undefined; data?: TCompany[] | undefined;
isLoading?: boolean; isLoading?: boolean;
refetch?: any;
}) { }) {
const moment = require("moment"); const moment = require("moment");
const [loadings, setLoadings] = useState<boolean[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [isBulkModalOpen, setIsBulkModalOpen] = useState(false);
const rowSelection = {
selectedRowKeys,
onChange: (keys: React.Key[], rows: TCompany[]) => {
setSelectedRowKeys(keys);
setSelectedIds(rows.map((row) => row?.id));
},
};
function getStatusClassName() { function getStatusClassName() {
if (role !== "Owner") { if (role !== "Owner") {
return "isnot"; return "isnot";
@ -37,8 +46,6 @@ function CompanyTable({
} }
} }
const { token } = theme.useToken();
const getImageSource = (source: string) => { const getImageSource = (source: string) => {
switch (source) { switch (source) {
case "Zippy": case "Zippy":
@ -58,12 +65,34 @@ function CompanyTable({
return ( return (
<div> <div>
{selectedIds.length !== 0 && (
<div
style={{
marginBottom: 16,
display: "flex",
alignItems: "center",
justifyContent: "end",
}}
>
<Button
type="primary"
disabled={selectedIds.length === 0}
onClick={() => setIsBulkModalOpen(true)}
>
Bulk Edit
</Button>
</div>
)}
<Table <Table
rowSelection={{
type: "checkbox",
...rowSelection,
}}
dataSource={data?.map((u, i) => ({ dataSource={data?.map((u, i) => ({
...u, ...u,
no: i + 1, no: i + 1,
created: moment(u?.created_at, "YYYY-MM-DD HH:mm:ss").format( created: moment(u?.created_at, "YYYY-MM-DD HH:mm:ss").format(
"DD.MM.YYYY HH:mm" "DD.MM.YYYY HH:mm",
), ),
key: u?.id, key: u?.id,
action: { ...u }, action: { ...u },
@ -152,25 +181,15 @@ function CompanyTable({
} }
size="small" size="small"
scroll={{ x: "768px" }} scroll={{ x: "768px" }}
// pagination={{
// pageSize: 10,
// size: "default",
// style: {
// margin: 0,
// justifyContent: "end",
// position: "fixed",
// bottom: 0,
// left: 0,
// width: "100%",
// backgroundColor: token.colorBgContainer,
// boxShadow: "0 4px 8px rgba(0, 0, 0, 0.4)",
// padding: "10px 0",
// zIndex: 1000,
// },
// }}
pagination={false} pagination={false}
bordered bordered
/> />
<BulkEditModal
open={isBulkModalOpen}
selectedIds={selectedIds}
onCancel={() => setIsBulkModalOpen(false)}
refetch={refetch}
/>
</div> </div>
); );
} }

@ -1,6 +1,7 @@
import { useMutation, useQuery, useQueryClient } from "react-query"; import { useMutation, useQuery, useQueryClient } from "react-query";
import { import {
TTeamGetParams, TTeamGetParams,
UpdateTeamMonitorCompaniesVars,
UpdateTeamMonitorVars, UpdateTeamMonitorVars,
teamController, teamController,
} from "../../API/LayoutApi/teams"; } from "../../API/LayoutApi/teams";
@ -16,7 +17,7 @@ export const useTeamData = ({
() => teamController.read({ name, company_id, page, page_size }), () => teamController.read({ name, company_id, page, page_size }),
{ {
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
} },
); );
}; };
@ -24,7 +25,7 @@ export const useTeamOne = (teamId: number | string | undefined): any => {
return useQuery( return useQuery(
[`team/${teamId || "all"}`, teamId], [`team/${teamId || "all"}`, teamId],
() => teamController.teamOne(teamId), () => teamController.teamOne(teamId),
{ refetchOnWindowFocus: false } { refetchOnWindowFocus: false },
); );
}; };
@ -40,7 +41,7 @@ export const useTeamsMonitorData = ({
() => teamController.readTeamsMonitor({ name, page, page_size }), () => teamController.readTeamsMonitor({ name, page, page_size }),
{ {
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
} },
); );
}; };
@ -90,6 +91,25 @@ export const useUpdateTeamMonitor = () => {
onError: (error) => { onError: (error) => {
console.error("Update team monitor failed:", error); console.error("Update team monitor failed:", error);
}, },
} },
);
};
export const useUpdateTeamMonitorCompanies = () => {
const queryClient = useQueryClient();
return useMutation(
({ id, payload }: UpdateTeamMonitorCompaniesVars) =>
teamController.updateTeamMonitorCompanies(id, payload),
{
onSuccess: () => {
queryClient.invalidateQueries("teams-monitor");
queryClient.invalidateQueries("companies");
},
onError: (error) => {
console.error("Update team monitor companies failed:", error);
},
},
); );
}; };

Loading…
Cancel
Save