dilmurod
Dilmurod 3 weeks ago
parent 472d9ab92f
commit 147901540a

@ -6,6 +6,7 @@ export type TStatGetParams = {
team?: string;
start_date?: string;
end_date?: string;
for_salary?: boolean;
};
export type TStatTeamGetParams = {

@ -5,6 +5,7 @@ import axios from "axios";
// });
const instance = axios.create({
baseURL: "https://api.tteld.co/api/v1/",
// baseURL: "http://10.10.10.64:8000/api/v1/",
});
const token: string | null = localStorage.getItem("access");

@ -278,6 +278,7 @@ const App: React.FC = () => {
// taskSocket = new WebSocket(`wss://api.tteld.co/global/?user_id=${admin_id}`);
taskSocket = new WebSocket(
`wss://ontime-socket.tteld.co/global/?user_id=${admin_id}`
// `ws://10.10.10.64:8000/global/?user_id=${admin_id}`
);
taskSocket.addEventListener("open", (event) => {
@ -481,7 +482,7 @@ const App: React.FC = () => {
>
<img src={themeBtn} alt="" />
</button>
<Dropdown overlay={menu} trigger={["hover"]}>
<Dropdown overlay={menu} trigger={["click"]}>
<div
style={{ cursor: "pointer" }}
onClick={(e) => e.preventDefault()}

@ -22,6 +22,16 @@ import {
import TabPane from "antd/es/tabs/TabPane";
// @ts-ignore
import IconSearch from "../../assets/searchIcon.png";
import {
CartesianGrid,
Legend,
Line,
LineChart,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from "recharts";
const Stat = () => {
const now = dayjs();
@ -37,6 +47,8 @@ const Stat = () => {
const [startDate, setStartDate] = useState(start_date);
const [endDate, setEndDate] = useState(end_date);
const [forSalary, setForSalary] = useState(true);
const teamData = useTeamData({});
const teamOptions: { label: string; value: any }[] | undefined =
teamData?.data?.map((item) => ({
@ -84,14 +96,21 @@ const Stat = () => {
setStartDate(`${yearStart}-${monthStart}-01 00:00:00`);
setEndDate(`${yearEnd}-${monthEnd}-01 00:00:00`);
setForSalary(true);
}
};
const clearDatePcker = () => {
setStartDate("");
setEndDate("");
};
const { data, refetch, isLoading } = useStatsData({
search: search,
team: team,
start_date: startDate,
end_date: endDate,
for_salary: forSalary,
});
interface DataType {
data?: TStatTeam[];
@ -118,6 +137,83 @@ const Stat = () => {
}, 1000);
};
const theme = localStorage.getItem("theme") === "true" ? true : false;
// const chartData = [
// {
// date: "2024-12-01",
// ABM: { points: 4500, count: 20 },
// ZNX: { points: 2500, count: 18 },
// TYP: { points: 3900, count: 24 },
// LMO: { points: 3100, count: 16 },
// QWE: { points: 2800, count: 21 },
// RST: { points: 4400, count: 19 },
// UVX: { points: 3950, count: 22 },
// WYZ: { points: 4100, count: 20 },
// ERT: { points: 3700, count: 17 },
// KLM: { points: 4200, count: 25 },
// LBS: { points: 1200, count: 25 },
// },
// {
// date: "2024-12-02",
// ABM: { points: 4600, count: 21 },
// ZNX: { points: 2400, count: 17 },
// TYP: { points: 3850, count: 23 },
// LMO: { points: 3200, count: 15 },
// QWE: { points: 2750, count: 20 },
// RST: { points: 4450, count: 18 },
// UVX: { points: 4000, count: 23 },
// WYZ: { points: 4200, count: 19 },
// ERT: { points: 3750, count: 16 },
// KLM: { points: 4250, count: 24 },
// LBS: { points: 1250, count: 26 },
// },
// {
// date: "2024-12-03",
// ABM: { points: 4550, count: 19 },
// ZNX: { points: 2550, count: 19 },
// TYP: { points: 3950, count: 25 },
// LMO: { points: 3150, count: 17 },
// QWE: { points: 2850, count: 22 },
// RST: { points: 4500, count: 20 },
// UVX: { points: 3900, count: 21 },
// WYZ: { points: 4300, count: 21 },
// ERT: { points: 3800, count: 18 },
// KLM: { points: 4300, count: 26 },
// LBS: { points: 1300, count: 27 },
// },
// ];
// const lines = [
// { key: "ABM.points", color: "#FF5733" }, // orange-red
// { key: "ZNX.points", color: "#00b822" }, // lime-green
// { key: "TYP.points", color: "#5733FF" }, // blue-purple
// { key: "LMO.points", color: "#FFC300" }, // gold
// { key: "QWE.points", color: "#009790" }, // turquoise
// { key: "RST.points", color: "#FF33A1" }, // hot pink
// { key: "UVX.points", color: "#8D33FF" }, // violet
// { key: "WYZ.points", color: "#FF8D33" }, // orange
// { key: "ERT.points", color: "#33A1FF" }, // sky blue
// { key: "KLM.points", color: "#4a8a01" }, // light green
// ];
// console.log(chartData, );
// const predefinedColors = ["#FF5733", "#00b822"];
// function updateLines(chartData: any, predefinedColors: any) {
// const keys = Object.keys(chartData[0]).filter((key) => key !== "date");
// const newLines = keys.map((key, index) => {
// const color = predefinedColors[index % predefinedColors.length]; // Ranglarni aylantirib foydalanadi
// return { key: `${key}.points`, color, name: `${key}` };
// });
// return newLines;
// }
// lines massivini yangilash
// const lines = updateLines(chartData, predefinedColors);
return (
<div>
<div
@ -183,6 +279,32 @@ const Stat = () => {
<Button type="primary" onClick={(e) => handleSave("")}>
Save as file
</Button>
{/* <ResponsiveContainer width="100%" height={400}>
<LineChart
width={800}
height={400}
data={chartData}
margin={{ top: 20, right: 30, left: 20, bottom: 10 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Legend />
{lines.map((line, index) => (
<Line
key={index}
type="linear"
dataKey={line.key}
name={line.name}
stroke={line.color}
activeDot={{ r: 7 }}
/>
))}
</LineChart>
</ResponsiveContainer> */}
</TabPane>
</Tabs>
</div>

@ -1,4 +1,4 @@
import { Table } from "antd";
import { Table, Tooltip } from "antd";
import { TStat } from "../../types/Statistic/TStat";
import {
QueryObserverResult,
@ -49,11 +49,43 @@ const StatTable = ({
dataIndex: "team_name",
key: "team_name ",
},
{
title: "Tasks",
dataIndex: "number_of_tasks",
key: "number_of_tasks",
},
{
title: "Points",
dataIndex: "total_points",
key: "total_points",
},
{
title: "Salary",
dataIndex: "salary",
key: "salary",
render: (text: string, record: any) => (
<Tooltip
title={
<div>
{record.salary_type === "Hybrid" ? (
<p>
<strong>Base Amount:</strong>{" "}
${record.salary_base_amount}
</p>
) : (
""
)}
<p>
<strong>Performance based amount:</strong>{" "}
${record.salary - record.salary_base_amount}
</p>
</div>
}
>
<span>${record.salary}</span>
</Tooltip>
),
},
]}
pagination={{
pageSize: 10,

@ -5,6 +5,8 @@ import {
RefetchOptions,
RefetchQueryFilters,
} from "react-query";
import { theme } from "antd";
// @ts-ignore
import tagIcon from "../../assets/tagIcon.png";
const StatTeamTable = ({
@ -18,6 +20,7 @@ const StatTeamTable = ({
data: TStatTeam[] | undefined;
isLoading: boolean;
}) => {
const { token } = theme.useToken();
return (
<div style={{ maxHeight: "400px", overflow: "auto" }}>
<Table
@ -36,6 +39,10 @@ const StatTeamTable = ({
title: "Team",
dataIndex: "name",
},
{
title: "Total tasks",
dataIndex: "number_of_tasks",
},
{
title: "Total points",
dataIndex: "total_points",
@ -64,7 +71,20 @@ const StatTeamTable = ({
},
]}
pagination={{
pageSize: 5,
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,
},
}}
rowClassName={(record, index) =>
index % 2 === 0 ? "odd-row" : "even-row"

@ -21,7 +21,9 @@ import Notfound from "../../Utils/Notfound";
import { useTeamData } from "../../Hooks/Teams";
import { useRoleData } from "../../Hooks/Role";
import { role } from "../../App";
import { useState } from "react";
import { useEffect, useState } from "react";
import { DollarOutlined } from "@ant-design/icons";
const TabPane = Tabs.TabPane;
type params = {
readonly id: string;
@ -29,13 +31,20 @@ type params = {
const UserEdit = () => {
const { id } = useParams<params>();
const { Option } = Select;
const { data, refetch, status } = useUserOne(id);
const initialUsername = data?.username;
const roleData = useRoleData();
const techSupport = roleData.data?.find(
(item) => item.name === "Tech Support"
);
const onSubmit = async (value: any) => {
if (initialUsername === value.username) {
value.username = undefined;
}
if (value.role_id === techSupport?.id) {
value.team_id = null;
@ -44,6 +53,11 @@ const UserEdit = () => {
id && (await userController.userPatch(value, id));
}
if (!value.salary_type) {
console.error("Salary type tanlanmagan!");
return;
}
refetch();
document.location.replace("/#/users/");
};
@ -69,6 +83,20 @@ const UserEdit = () => {
}
};
const [activeTab, setActiveTab] = useState("1");
const [showInput, setShowInput] = useState(false);
const handleChange = (value: string) => {
// Agar Hybrid bo'lsa, inputni ko'rsatish; Task based bo'lsa, yashirish
setShowInput(value === "hybrid");
};
useEffect(() => {
if (data?.salary_type === "hybrid") {
setShowInput(true);
}
}, [data]);
return (
<div>
<Spin size="large" spinning={!data}>
@ -169,6 +197,34 @@ const UserEdit = () => {
</Form.Item>
</Col>
)}
{data.role.name === "Checker" && (
<Col span={4}>
<Form.Item
wrapperCol={{ span: "100%" }}
label="Salary type"
name="salary_type" // Form ma'lumotlarini yuborish uchun 'name' qo'shilgan
>
<Select
onChange={handleChange}
placeholder="Select salary type"
>
<Option value="task_based">Task based</Option>
<Option value="hybrid">Hybrid</Option>
</Select>
</Form.Item>
</Col>
)}
{showInput && (
<Form.Item
wrapperCol={{ span: "100%" }}
label="Base amount"
name="salary_base_amount"
>
<Input prefix={<DollarOutlined />} />
</Form.Item>
)}
</Row>
<Form.Item>
{role !== "Checker" && (

@ -1,43 +1,52 @@
import { useQuery } from "react-query";
import { TStatGetParams, statController } from "../../API/LayoutApi/statistic";
export const useStatsData = ({search, team, start_date, end_date}: TStatGetParams) => {
return useQuery(
[`stats/all-users/`, search, team, start_date, end_date],
() => statController.read({search, team, start_date, end_date}),
{ refetchOnWindowFocus: false }
);
export const useStatsData = ({
search,
team,
start_date,
end_date,
for_salary,
}: TStatGetParams) => {
return useQuery(
[`stats/all-users/`, search, team, start_date, end_date, for_salary],
() =>
statController.read({ search, team, start_date, end_date, for_salary }),
{ refetchOnWindowFocus: false }
);
};
export const useStatTeamData = ({search, start_date, end_date}: TStatGetParams) => {
return useQuery(
[`stats/all-teams/`, search, start_date, end_date],
() => statController.team({search, start_date, end_date}),
{ refetchOnWindowFocus: false }
);
export const useStatTeamData = ({
search,
start_date,
end_date,
}: TStatGetParams) => {
return useQuery(
[`stats/all-teams/`, search, start_date, end_date],
() => statController.team({ search, start_date, end_date }),
{ refetchOnWindowFocus: false }
);
};
export const useCreatorsData = ({ start_date, end_date}: TStatGetParams) => {
return useQuery(
[`stats/task-creators/`, start_date, end_date],
() => statController.creators({ start_date, end_date}),
{ refetchOnWindowFocus: false }
);
export const useCreatorsData = ({ start_date, end_date }: TStatGetParams) => {
return useQuery(
[`stats/task-creators/`, start_date, end_date],
() => statController.creators({ start_date, end_date }),
{ refetchOnWindowFocus: false }
);
};
export const useCardData = ({ start_date, end_date}: TStatGetParams) => {
return useQuery(
[`stats/tasks-comparison/`, start_date, end_date],
() => statController.cards({ start_date, end_date}),
{ refetchOnWindowFocus: false }
);
export const useCardData = ({ start_date, end_date }: TStatGetParams) => {
return useQuery(
[`stats/tasks-comparison/`, start_date, end_date],
() => statController.cards({ start_date, end_date }),
{ refetchOnWindowFocus: false }
);
};
export const useStatOne = (
statId: number | string | undefined
): any => {
return useQuery(
[`stat/${statId || "all"}`, statId],
() => statController.statOne(statId),
{ refetchOnWindowFocus: false }
);
export const useStatOne = (statId: number | string | undefined): any => {
return useQuery(
[`stat/${statId || "all"}`, statId],
() => statController.statOne(statId),
{ refetchOnWindowFocus: false }
);
};

@ -1,21 +1,22 @@
export type TStat = {
id: number;
full_name: string;
username: string;
team_id: number | null;
total_points: number;
}
id: number;
full_name: string;
username: string;
team_id: number | null;
total_points: number;
for_salary: boolean;
};
export type TStatTeam = {
id: number;
name: string;
is_active: boolean;
total_points: number;
}
id: number;
name: string;
is_active: boolean;
total_points: number;
};
export type TCard = {
all_tasks: number;
active_tasks: number;
active_tasks_percentage: number;
inactive_tasks: number;
inactive_tasks_percentage: number;
}
export type TCard = {
all_tasks: number;
active_tasks: number;
active_tasks_percentage: number;
inactive_tasks: number;
inactive_tasks_percentage: number;
};

@ -7,4 +7,6 @@ export type TUser = {
last_name: string | '';
is_active: boolean;
is_superuser: boolean;
salary_type: string;
salary_base_amount: number;
}
Loading…
Cancel
Save