Pārlūkot izejas kodu

Merge branch 'main' of https://git.2fi-solutions.com/wayne.lee/tsms

tags/Baseline_30082024_FRONTEND_UAT
MSI\2Fi pirms 1 gada
vecāks
revīzija
e87c288e74
11 mainītis faili ar 832 papildinājumiem un 0 dzēšanām
  1. +29
    -0
      src/app/(main)/dashboard/ProjectStatusByTeam/page.tsx
  2. +43
    -0
      src/app/api/teamprojects/index.ts
  3. +10
    -0
      src/components/CompanyTeamCashFlow/CompanyTeamCashFlow.tsx
  4. +5
    -0
      src/components/NavigationContent/NavigationContent.tsx
  5. +620
    -0
      src/components/ProgressByTeam/ProgressByTeam.tsx
  6. +1
    -0
      src/components/ProgressByTeam/index.ts
  7. +55
    -0
      src/components/ProgressByTeamSearch/ProgressByTeamSearch.tsx
  8. +40
    -0
      src/components/ProgressByTeamSearch/ProgressByTeamSearchLoading.tsx
  9. +18
    -0
      src/components/ProgressByTeamSearch/ProgressByTeamSearchWrapper.tsx
  10. +1
    -0
      src/components/ProgressByTeamSearch/index.ts
  11. +10
    -0
      src/components/ProjectCashFlow/ProjectCashFlow.tsx

+ 29
- 0
src/app/(main)/dashboard/ProjectStatusByTeam/page.tsx Parādīt failu

@@ -0,0 +1,29 @@
import { Metadata } from "next";
import { I18nProvider } from "@/i18n";
import DashboardPage from "@/components/DashboardPage/DashboardPage";
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton";
import ProgressByTeamSearch from "@/components/ProgressByTeamSearch";
import { Suspense } from "react";
import Tabs, { TabsProps } from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import Typography from "@mui/material/Typography";
import ProgressByTeam from "@/components/ProgressByTeam";

export const metadata: Metadata = {
title: "Project Status by Team",
};

const ProjectStatusByTeam: React.FC = () => {
return (
<I18nProvider namespaces={["dashboard"]}>
<Typography variant="h4" marginInlineEnd={2}>
Project Status by Team
</Typography>
<Suspense fallback={<ProgressByTeamSearch.Loading />}>
<ProgressByTeamSearch />
</Suspense>
<ProgressByTeam />
</I18nProvider>
);
};
export default ProjectStatusByTeam;

+ 43
- 0
src/app/api/teamprojects/index.ts Parādīt failu

@@ -0,0 +1,43 @@
import { cache } from "react";

export interface TeamProjectResult {
id: number;
teamCode: string;
teamName: string;
NoOfProjects: number;
}

export const preloadProjects = () => {
fetchTeamProjects();
};

export const fetchTeamProjects = cache(async () => {
return mockProjects;
});

const mockProjects: TeamProjectResult[] = [
{
id: 1,
teamCode: "TEAM-001",
teamName: "Team A",
NoOfProjects: 5,
},
{
id: 2,
teamCode: "TEAM-002",
teamName: "Team B",
NoOfProjects: 5,
},
{
id: 3,
teamCode: "TEAM-003",
teamName: "Team C",
NoOfProjects: 3,
},
{
id: 4,
teamCode: "TEAM-004",
teamName: "Team D",
NoOfProjects: 1,
},
];

+ 10
- 0
src/components/CompanyTeamCashFlow/CompanyTeamCashFlow.tsx Parādīt failu

@@ -160,6 +160,11 @@ const CompanyTeamCashFlow: React.FC = () => {
min: 0,
max: 3700000,
tickAmount: 5,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
show: false,
@@ -180,6 +185,11 @@ const CompanyTeamCashFlow: React.FC = () => {
min: 0,
max: 21000000,
tickAmount: 5,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
show: false,


+ 5
- 0
src/components/NavigationContent/NavigationContent.tsx Parādīt failu

@@ -63,6 +63,11 @@ const navigationItems: NavigationItem[] = [
label: "Project Status by Client",
path: "/dashboard/ProjectStatusByClient",
},
{
icon: <AccountTreeIcon />,
label: "Project Status by Team",
path: "/dashboard/ProjectStatusByTeam",
},
{
icon: <PeopleIcon />,
label: "Staff Utilization",


+ 620
- 0
src/components/ProgressByTeam/ProgressByTeam.tsx Parādīt failu

@@ -0,0 +1,620 @@
"use client";
import * as React from "react";
import Grid from "@mui/material/Grid";
import { useState, useEffect, useMemo } from "react";
import Paper from "@mui/material/Paper";
import { TFunction } from "i18next";
import { useTranslation } from "react-i18next";
import { Card, CardHeader } from "@mui/material";
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
import ReactApexChart from "react-apexcharts";
import { ApexOptions } from "apexcharts";
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
import ReportProblemIcon from "@mui/icons-material/ReportProblem";
import dynamic from "next/dynamic";
import "../../app/global.css";
import { AnyARecord, AnyCnameRecord } from "dns";
import SearchBox, { Criterion } from "../SearchBox";
import ProgressByTeamSearch from "@/components/ProgressByTeamSearch";
import { Suspense } from "react";

const ProgressByTeam: React.FC = () => {
const [activeTab, setActiveTab] = useState("financialSummary");
const [SearchCriteria, setSearchCriteria] = React.useState({});
const { t } = useTranslation("dashboard");

const [teamCode, setTeamCode] = useState("");
const [teamName, setTeamName] = useState("");
const [projectArray, setProjectArray]: any[] = useState([]);
const [percentageArray, setPercentageArray]: any[] = useState([]);
const [colorArray, setColorArray]: any[] = useState([]);
const [selectionModel, setSelectionModel]: any[] = React.useState([]);
const [pieChartColor, setPieChartColor]: any[] = React.useState([]);
const [totalSpentPercentage, setTotalSpentPercentage]: any = React.useState();
const [projectBudgetManhour, setProjectBudgetManhour]: any =
React.useState("-");
const [actualManhourSpent, setActualManhourSpent]: any = React.useState("-");
const [remainedManhour, setRemainedManhour]: any = React.useState("-");
const [lastUpdate, setLastUpdate]: any = React.useState("-");
const [dropdownDemo, setDropdownDemo] = useState("");
const [dateDemo, setDateDemo] = useState(null);
const [checkboxDemo, setCheckboxDemo] = useState(false);
const [receiptFromDate, setReceiptFromDate] = useState(null);
const [receiptToDate, setReceiptToDate] = useState(null);
const [selectedRows, setSelectedRows] = useState([]);
const rows = [
{
id: 1,
teamCode: "TEAM-001",
teamName: "Team A",
noOfProjects: "5",
},
{
id: 2,
teamCode: "TEAM-001",
teamName: "Team B",
noOfProjects: "5",
},
{
id: 3,
teamCode: "TEAM-001",
teamName: "Team C",
noOfProjects: "3",
},
{
id: 4,
teamCode: "TEAM-001",
teamName: "Team D",
noOfProjects: "1",
},
];
//['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b']
const rows2 = [
{
id: 1,
project: "Consultancy Project 123",
team: "XXX",
teamLeader: "XXX",
currentStage: "Contract Documentation",
budgetedManhour: "200.00",
spentManhour: "120.00",
remainedManhour: "80.00",
comingPaymentMilestone: "31/03/2024",
alert: false,
color: "#f57f90",
},
{
id: 2,
project: "Consultancy Project 456",
team: "XXX",
teamLeader: "XXX",
currentStage: "Report Preparation",
budgetedManhour: "400.00",
spentManhour: "200.00",
remainedManhour: "200.00",
comingPaymentMilestone: "20/02/2024",
alert: false,
color: "#94f7d6",
},
{
id: 3,
project: "Construction Project A",
team: "YYY",
teamLeader: "YYY",
currentStage: "Construction",
budgetedManhour: "187.50",
spentManhour: "200.00",
remainedManhour: "12.50",
comingPaymentMilestone: "13/12/2023",
alert: true,
color: "#87c5f5",
},
{
id: 4,
project: "Construction Project B",
team: "XXX",
teamLeader: "XXX",
currentStage: "Post Construction",
budgetedManhour: "100.00",
spentManhour: "40.00",
remainedManhour: "60.00",
comingPaymentMilestone: "05/01/2024",
alert: false,
color: "#ab95f5",
},
{
id: 5,
project: "Construction Project C",
team: "YYY",
teamLeader: "YYY",
currentStage: "Construction",
budgetedManhour: "300.00",
spentManhour: "150.00",
remainedManhour: "150.00",
comingPaymentMilestone: "31/03/2024",
alert: false,
color: "#fcd68b",
},
];

const columns = [
{
id: "clientCode",
field: "clientCode",
headerName: "Client Code",
flex: 1,
},
{
id: "clientName",
field: "clientName",
headerName: "Client Name",
flex: 1,
},
{
id: "clientSubsidiaryCode",
field: "clientSubsidiaryCode",
headerName: "Client Subsidiary Code",
flex: 1,
},
{
id: "noOfProjects",
field: "noOfProjects",
headerName: "No. of Projects",
flex: 1,
},
];

const columns2 = [
{
id: "color",
field: "color",
headerName: "",
renderCell: (params: any) => {
return (
<span
className="dot"
style={{
height: "15px",
width: "15px",
borderRadius: "50%",
backgroundColor: `${params.row.color}`,
display: "inline-block",
}}
></span>
);
},
flex: 0.1,
},
{
id: "project",
field: "project",
headerName: "Project",
flex: 1,
},
{
id: "team",
field: "team",
headerName: "Team",
flex: 0.8,
},
{
id: "teamLeader",
field: "teamLeader",
headerName: "Team Leader",
flex: 0.8,
},
{
id: "currentStage",
field: "currentStage",
headerName: "Current Stage",
flex: 1,
},
{
id: "budgetedManhour",
field: "budgetedManhour",
headerName: "Budgeted Manhour",
flex: 0.8,
},
{
id: "spentManhour",
field: "spentManhour",
headerName: "Spent Manhour",
renderCell: (params: any) => {
if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
return (
<span className="text-red-300">{params.row.spentManhour}</span>
);
} else {
return <span>{params.row.spentManhour}</span>;
}
},
flex: 0.8,
},
{
id: "remainedManhour",
field: "remainedManhour",
headerName: "Remained Manhour",
renderCell: (params: any) => {
if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
return (
<span className="text-red-300">({params.row.remainedManhour})</span>
);
} else {
return <span>{params.row.remainedManhour}</span>;
}
},
flex: 1,
},
{
id: "comingPaymentMilestone",
field: "comingPaymentMilestone",
headerName: "Coming Payment Milestone",
flex: 1,
},
{
id: "alert",
field: "alert",
headerName: "Alert",
renderCell: (params: any) => {
if (params.row.alert === true) {
return (
<span className="text-red-300 text-center">
<ReportProblemIcon />
</span>
);
} else {
return <span></span>;
}
},
flex: 0.2,
},
];

const InputFields = [
{
id: "teamCode",
label: "Team Code",
type: "text",
value: teamCode,
setValue: setTeamCode,
},
{
id: "teamName",
label: "Team Name",
type: "text",
value: teamName,
setValue: setTeamName,
},
// { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo },
// { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo },
// { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo },
// { id: ['receiptFromDate','receiptToDate'], label: ["收貨日期","收貨日期"], value: [receiptFromDate ? receiptFromDate : null, receiptToDate ? receiptToDate : null],
// setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' },
];

const stageDeadline = [
"31/03/2024",
"20/02/2024",
"01/12/2023",
"05/01/2024",
"31/03/2023",
];

const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [
{
data: [17.1, 28.6, 5.7, 48.6],
},
];

const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [
{
name: "Current Stage Completion Percentage",
data: [80, 55, 40, 65, 70],
},
];

const options2: ApexOptions = {
chart: {
type: "donut",
},
colors: colorArray,
plotOptions: {
pie: {
donut: {
labels: {
show: true,
name: {
show: true,
},
value: {
show: true,
fontWeight: 500,
fontSize: "30px",
color: "#3e98c7",
},
total: {
show: true,
showAlways: true,
label: "Spent",
fontFamily: "sans-serif",
formatter: function (val) {
return totalSpentPercentage + "%";
},
},
},
},
},
},
labels: projectArray,
legend: {
show: false,
},
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 200,
},
legend: {
position: "bottom",
show: false,
},
},
},
],
};

const options: ApexOptions = {
chart: {
type: "bar",
height: 350,
},
colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"],
plotOptions: {
bar: {
horizontal: true,
distributed: true,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: [
"Consultancy Project 123",
"Consultancy Project 456",
"Construction Project A",
"Construction Project B",
"Construction Project C",
],
},
yaxis: {
title: {
text: "Projects",
},
labels: {
maxWidth: 200,
style: {
cssClass: "apexcharts-yaxis-label",
},
},
},
title: {
text: "Current Stage Completion Percentage",
align: "center",
},
grid: {
borderColor: "#f1f1f1",
},
annotations: {},
};

const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
const selectedRowsData = rows2.filter((row) =>
newSelectionModel.includes(row.id),
);
console.log(selectedRowsData);
const projectArray = [];
const pieChartColorArray = [];
let totalSpent = 0;
let totalBudgetManhour = 0;
const percentageArray = [];
for (let i = 0; i <= selectedRowsData.length; i++) {
if (i === selectedRowsData.length && i > 0) {
projectArray.push("Remained");
} else if (selectedRowsData.length > 0) {
projectArray.push(selectedRowsData[i].project);
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour);
totalSpent += Number(selectedRowsData[i].spentManhour);
pieChartColorArray.push(selectedRowsData[i].color);
}
}
for (let i = 0; i <= selectedRowsData.length; i++) {
if (i === selectedRowsData.length && i > 0) {
const remainedManhour = totalBudgetManhour - totalSpent;
percentageArray.push(
Number(((remainedManhour / totalBudgetManhour) * 100).toFixed(1)),
);
} else if (selectedRowsData.length > 0) {
const percentage = (
(Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) *
100
).toFixed(1);
percentageArray.push(Number(percentage));
}
}
setProjectBudgetManhour(totalBudgetManhour.toFixed(2));
setActualManhourSpent(totalSpent.toFixed(2));
setRemainedManhour((totalBudgetManhour - totalSpent).toFixed(2));
setLastUpdate(new Date().toLocaleDateString("en-GB"));
setSelectionModel(newSelectionModel);
console.log(projectArray);
setProjectArray(projectArray);
setPercentageArray(percentageArray);
console.log(percentageArray);
setTotalSpentPercentage(
((totalSpent / totalBudgetManhour) * 100).toFixed(1),
);
if (projectArray.length > 0 && projectArray.includes("Remained")) {
const nonLastRecordColors = pieChartColorArray;
setColorArray([
...nonLastRecordColors.slice(0, projectArray.length - 1),
"#a3a3a3",
]);
} else {
setColorArray(pieChartColorArray);
}
};

const applySearch = (data: any) => {
console.log(data);
setSearchCriteria(data);
};
return (
<Grid item sm>
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */}
{/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */}
<div style={{ display: "inline-block", width: "70%" }}>
<Grid item xs={12} md={12} lg={12}>
<Card>
<CardHeader className="text-slate-500" title="Project Progress" />
<div style={{ display: "inline-block", width: "99%" }}>
<ReactApexChart
options={options}
series={series}
type="bar"
height={350}
/>
</div>
{/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}>
<p><strong><u>Stage Deadline</u></strong></p>
{stageDeadline.map((date, index) => {
const marginTop = index === 0 ? 25 : 20;
return (
<p style={{marginTop:marginTop}} key={index}>{date}</p>
);
})}
</div> */}
<CardHeader
className="text-slate-500"
title="Current Stage Due Date"
/>
<div
style={{ display: "inline-block", width: "99%", marginLeft: 10 }}
>
<CustomDatagrid
rows={rows2}
columns={columns2}
columnWidth={200}
dataGridHeight={300}
checkboxSelection={true}
onRowSelectionModelChange={handleSelectionChange}
selectionModel={selectionModel}
/>
</div>
</Card>
</Grid>
</div>
<div
style={{
display: "inline-block",
width: "30%",
verticalAlign: "top",
marginLeft: 0,
}}
>
<Grid item xs={12} md={12} lg={12}>
<Card style={{ marginLeft: 15, marginRight: 20 }}>
<CardHeader
className="text-slate-500"
title="Overall Progress per Project"
/>
{percentageArray.length === 0 && (
<div
className="mt-10 mb-10 ml-5 mr-5 text-lg font-medium text-center"
style={{ color: "#898d8d" }}
>
Please select the project you want to check.
</div>
)}
{percentageArray.length > 0 && (
<ReactApexChart
options={options2}
series={percentageArray}
type="donut"
/>
)}
</Card>
</Grid>
<Grid item xs={12} md={12} lg={12}>
<Card style={{ marginLeft: 15, marginRight: 20, marginTop: 20 }}>
<div>
<div
className="mt-5 text-lg font-medium"
style={{ color: "#898d8d" }}
>
<span style={{ marginLeft: "5%" }}>Project Budget Manhour</span>
</div>
<div
className="mt-2 text-2xl font-extrabold"
style={{ color: "#6b87cf" }}
>
<span style={{ marginLeft: "5%" }}>{projectBudgetManhour}</span>
</div>
</div>
<hr />
<div>
<div
className="mt-2 text-lg font-medium"
style={{ color: "#898d8d" }}
>
<span style={{ marginLeft: "5%" }}>Actual Manhour Spent</span>
</div>
<div
className="mt-2 text-2xl font-extrabold"
style={{ color: "#6b87cf" }}
>
<span style={{ marginLeft: "5%" }}>{actualManhourSpent}</span>
</div>
</div>
<hr />
<div>
<div
className="mt-2 text-lg font-medium"
style={{ color: "#898d8d" }}
>
<span style={{ marginLeft: "5%" }}>Remained Manhour</span>
</div>
<div
className="mt-2 text-2xl font-extrabold"
style={{ color: "#6b87cf" }}
>
<span style={{ marginLeft: "5%" }}>{remainedManhour}</span>
</div>
</div>
<hr />
<div>
<div
className="mt-2 text-lg font-medium"
style={{ color: "#898d8d" }}
>
<span style={{ marginLeft: "5%" }}>Last Update</span>
</div>
<div
className="mt-2 mb-5 text-2xl font-extrabold"
style={{ color: "#6b87cf" }}
>
<span style={{ marginLeft: "5%" }}>{lastUpdate}</span>
</div>
</div>
</Card>
</Grid>
</div>
</Grid>
);
};

export default ProgressByTeam;

+ 1
- 0
src/components/ProgressByTeam/index.ts Parādīt failu

@@ -0,0 +1 @@
export { default } from "./ProgressByTeam";

+ 55
- 0
src/components/ProgressByTeamSearch/ProgressByTeamSearch.tsx Parādīt failu

@@ -0,0 +1,55 @@
"use client";

import { ProjectResult } from "@/app/api/projects";
import React, { useMemo, useState } from "react";
import SearchBox, { Criterion } from "../SearchBox";
import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults";
import { TeamProjectResult } from "@/app/api/teamprojects";

interface Props {
projects: TeamProjectResult[];
}
type SearchQuery = Partial<Omit<TeamProjectResult, "id">>;
type SearchParamNames = keyof SearchQuery;

const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
const { t } = useTranslation("projects");

// If project searching is done on the server-side, then no need for this.
const [filteredProjects, setFilteredProjects] = useState(projects);

const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
() => [
{ label: "Team Code", paramName: "teamCode", type: "text" },
{ label: "Team Name", paramName: "teamName", type: "text" },
],
[t],
);

const columns = useMemo<Column<TeamProjectResult>[]>(
() => [
{ name: "teamCode", label: t("Team Code") },
{ name: "teamName", label: t("Team Name") },
{ name: "NoOfProjects", label: t("No. of Projects") },
],
[t],
);

return (
<>
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
console.log(query);
}}
/>
<SearchResults<TeamProjectResult>
items={filteredProjects}
columns={columns}
/>
</>
);
};

export default ProgressByClientSearch;

+ 40
- 0
src/components/ProgressByTeamSearch/ProgressByTeamSearchLoading.tsx Parādīt failu

@@ -0,0 +1,40 @@
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Skeleton from "@mui/material/Skeleton";
import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const ProgressByTeamSearchLoading: React.FC = () => {
return (
<>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton
variant="rounded"
height={50}
width={100}
sx={{ alignSelf: "flex-end" }}
/>
</Stack>
</CardContent>
</Card>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
</Stack>
</CardContent>
</Card>
</>
);
};

export default ProgressByTeamSearchLoading;

+ 18
- 0
src/components/ProgressByTeamSearch/ProgressByTeamSearchWrapper.tsx Parādīt failu

@@ -0,0 +1,18 @@
import { fetchTeamProjects } from "@/app/api/teamprojects";
import React from "react";
import ProgressByTeamSearch from "./ProgressByTeamSearch";
import ProgressByTeamSearchLoading from "./ProgressByTeamSearchLoading";

interface SubComponents {
Loading: typeof ProgressByTeamSearchLoading;
}

const ProgressByTeamSearchWrapper: React.FC & SubComponents = async () => {
const teamprojects = await fetchTeamProjects();

return <ProgressByTeamSearch projects={teamprojects} />;
};

ProgressByTeamSearchWrapper.Loading = ProgressByTeamSearchLoading;

export default ProgressByTeamSearchWrapper;

+ 1
- 0
src/components/ProgressByTeamSearch/index.ts Parādīt failu

@@ -0,0 +1 @@
export { default } from "./ProgressByTeamSearchWrapper";

+ 10
- 0
src/components/ProjectCashFlow/ProjectCashFlow.tsx Parādīt failu

@@ -152,6 +152,11 @@ const ProjectCashFlow: React.FC = () => {
min: 0,
max: 350000,
tickAmount: 5,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
show: false,
@@ -172,6 +177,11 @@ const ProjectCashFlow: React.FC = () => {
min: 0,
max: 850000,
tickAmount: 5,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
show: false,


Notiek ielāde…
Atcelt
Saglabāt