@esic-lab/data-core-ui 0.0.64 → 0.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -621,9 +621,9 @@ function Checkbox({ label, checked, onChange, disabled }) {
621
621
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
622
622
  "div",
623
623
  {
624
- className: `flex justify-center items-center border-[1px] border-black w-[24px] h-[24px] rounded-[8px] transition-colors duration-100
625
- ${checked ? "bg-black text-white" : "bg-white text-black"}
626
- ${disabled ? "pointer-events-none" : ""}`,
624
+ className: `flex justify-center items-center border-[1px] border-gray-400 w-[24px] h-[24px] rounded-[8px] transition-colors duration-100
625
+ ${checked ? "bg-primary-500 text-white border-primary-500" : "bg-white text-black"}
626
+ ${disabled ? "pointer-events-none !bg-gray-300" : ""}`,
627
627
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
628
628
  "span",
629
629
  {
@@ -4143,7 +4143,7 @@ function Indicator({
4143
4143
  }
4144
4144
  ),
4145
4145
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_icons_react12.IconX, { className: "cursor-pointer text-red-600", onClick: handleCancelEditIndicator })
4146
- ] }) : void 0 : canEdit && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_icons_react12.IconPencil, { className: "cursor-pointer", onClick: () => handleEditIndicator(index) }) }),
4146
+ ] }) : void 0 : false }),
4147
4147
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "body-1 mt-2 cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4148
4148
  import_icons_react12.IconTrash,
4149
4149
  {
@@ -4798,6 +4798,8 @@ var PieChart = ({
4798
4798
  var import_react24 = require("react");
4799
4799
  var d33 = __toESM(require("d3"));
4800
4800
  var import_date_fns3 = require("date-fns");
4801
+ var import_locale3 = require("date-fns/locale");
4802
+ var import_icons_react15 = require("@tabler/icons-react");
4801
4803
  var import_jsx_runtime48 = require("react/jsx-runtime");
4802
4804
  var LAYOUT = {
4803
4805
  barHeight: 40,
@@ -4815,31 +4817,33 @@ var VIEW_MODE_SCALE = {
4815
4817
  week: 10
4816
4818
  };
4817
4819
  var STATUS_META = {
4818
- pending: { color: "#F16965", label: "\u0E23\u0E2D\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23" },
4819
- "in-progress": { color: "#FFBB33", label: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23" },
4820
- completed: { color: "#69C57D", label: "\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E2A\u0E34\u0E49\u0E19" }
4821
- };
4822
- var THAI_MONTHS = {
4823
- January: "\u0E21.\u0E04.",
4824
- February: "\u0E01.\u0E1E.",
4825
- March: "\u0E21\u0E35.\u0E04.",
4826
- April: "\u0E40\u0E21.\u0E22.",
4827
- May: "\u0E1E.\u0E04.",
4828
- June: "\u0E21\u0E34.\u0E22.",
4829
- July: "\u0E01.\u0E04.",
4830
- August: "\u0E2A.\u0E04.",
4831
- September: "\u0E01.\u0E22.",
4832
- October: "\u0E15.\u0E04.",
4833
- November: "\u0E1E.\u0E22.",
4834
- December: "\u0E18.\u0E04."
4820
+ IN_PROGRESS: {
4821
+ color: "#FFC654",
4822
+ label: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23",
4823
+ icon: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_icons_react15.IconHourglassEmpty, { className: "text-[#FFC654]" })
4824
+ },
4825
+ CANCEL: {
4826
+ color: "#D2D5DB",
4827
+ label: "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",
4828
+ icon: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_icons_react15.IconCircleX, { className: "text-[#D2D5DB]" })
4829
+ },
4830
+ SUCCESS: {
4831
+ color: "#81CF92",
4832
+ label: "\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23\u0E41\u0E25\u0E49\u0E27\u0E40\u0E2A\u0E23\u0E47\u0E08",
4833
+ icon: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_icons_react15.IconRosetteDiscountCheck, { className: "text-[#81CF92]" })
4834
+ },
4835
+ COMPLETE: {
4836
+ color: "#81CF92",
4837
+ label: "\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E2A\u0E34\u0E49\u0E19",
4838
+ icon: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_icons_react15.IconRosetteDiscountCheck, { className: "text-[#81CF92]" })
4839
+ },
4840
+ DELAY: {
4841
+ color: "#F4827E",
4842
+ label: "\u0E25\u0E48\u0E32\u0E0A\u0E49\u0E32",
4843
+ icon: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_icons_react15.IconClockExclamation, { className: "text-[#F4827E]" })
4844
+ }
4835
4845
  };
4836
- var THAI_DAYS = ["\u0E2D\u0E32.", "\u0E08.", "\u0E2D.", "\u0E1E.", "\u0E1E\u0E24.", "\u0E28.", "\u0E2A."];
4837
4846
  var roundedRectPath = (x, y, width, height, radius) => `M${x + radius},${y} H${x + width} V${y + height} H${x + radius} A${radius},${radius},0,0,1,${x},${y + height - radius} V${y + radius} A${radius},${radius},0,0,1,${x + radius},${y}`;
4838
- var formatThaiMonth = (date) => {
4839
- const monthName = (0, import_date_fns3.format)(date, "MMMM");
4840
- return THAI_MONTHS[monthName] || monthName;
4841
- };
4842
- var formatThaiDate = (date) => date ? date.toLocaleDateString("th-TH", { day: "numeric", month: "short" }) : "-";
4843
4847
  var isDateOnlyValue = (dt) => {
4844
4848
  const localZero = dt.getHours() === 0 && dt.getMinutes() === 0 && dt.getSeconds() === 0 && dt.getMilliseconds() === 0;
4845
4849
  const utcZero = dt.getUTCHours() === 0 && dt.getUTCMinutes() === 0 && dt.getUTCSeconds() === 0 && dt.getUTCMilliseconds() === 0;
@@ -4869,60 +4873,46 @@ var getAdjustedEnd = (d) => {
4869
4873
  }
4870
4874
  return (0, import_date_fns3.startOfDay)(/* @__PURE__ */ new Date());
4871
4875
  };
4872
- var getStatusColor = (status2) => STATUS_META[status2]?.color ?? STATUS_META.pending.color;
4873
- var getStatusLabel = (status2) => STATUS_META[status2]?.label ?? STATUS_META.pending.label;
4874
- var ProjectRow = ({ element, barHeight, barSpacing }) => {
4876
+ var getStatusColor = (status2) => STATUS_META[status2]?.color ?? STATUS_META.IN_PROGRESS.color;
4877
+ var getStatusLabel = (status2) => STATUS_META[status2]?.label ?? STATUS_META.IN_PROGRESS.label;
4878
+ var ProjectRow = ({ element, barHeight, barSpacing, mode }) => {
4875
4879
  const safeStartDate = element.startDate instanceof Date ? element.startDate : null;
4876
4880
  const safeEndDate = element.endDate instanceof Date ? element.endDate : null;
4877
4881
  const safeStatus = element.status || "pending";
4878
4882
  const statusColor = getStatusColor(safeStatus);
4879
4883
  const statusLabel = getStatusLabel(safeStatus);
4884
+ const statusIcon = STATUS_META[safeStatus]?.icon;
4885
+ const toBuddhistDate = (d) => new Date(d.getFullYear() + 543, d.getMonth(), d.getDate());
4880
4886
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
4881
4887
  "div",
4882
4888
  {
4883
4889
  style: {
4884
- display: "grid",
4885
- gridTemplateColumns: "200px 100px 100px 100px",
4886
4890
  alignItems: "center",
4887
4891
  height: `${barHeight}px`,
4888
- fontSize: "12px",
4889
- marginBottom: `${barSpacing}px`
4892
+ marginBottom: `${barSpacing}px`,
4893
+ fontSize: "12px"
4890
4894
  },
4895
+ className: "body-1 grid grid-cols-[1fr_100px_130px] px-8 gap-2",
4891
4896
  children: [
4892
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4893
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4894
- "span",
4897
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: `grid ${mode === "project" ? "grid-cols-[10px_1fr]" : "grid-cols-[1fr]"} items-center gap-2`, children: [
4898
+ mode === "project" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4899
+ "div",
4895
4900
  {
4896
4901
  style: {
4897
- display: "inline-block",
4898
- width: "10px",
4899
- height: "10px",
4900
- borderRadius: "50%",
4901
- backgroundColor: element.color || "#999"
4902
- }
4902
+ backgroundColor: element.color || "#E9E9E9"
4903
+ },
4904
+ className: "w-[10px] h-[10px] rounded-full"
4903
4905
  }
4904
4906
  ),
4905
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { color: "#333" }, children: element.label })
4907
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "line-clamp-1 break-words text-[#333]", title: element.label, children: element.label })
4906
4908
  ] }),
4907
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { style: { color: "#666" }, children: formatThaiDate(safeStartDate) }),
4908
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { style: { color: "#666" }, children: formatThaiDate(safeEndDate) }),
4909
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4910
- "button",
4911
- {
4912
- style: {
4913
- height: `${barHeight}px`,
4914
- minWidth: "100%",
4915
- padding: "4px 8px",
4916
- borderRadius: "4px",
4917
- fontSize: "11px",
4918
- backgroundColor: statusColor,
4919
- color: "#000",
4920
- border: "none",
4921
- cursor: "pointer"
4922
- },
4923
- children: statusLabel
4924
- }
4925
- )
4909
+ mode === "project" ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: safeEndDate ? (0, import_date_fns3.format)(toBuddhistDate(safeEndDate), "dd MMM yyyy", { locale: import_locale3.th }) : "-" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: `Q${(0, import_date_fns3.getQuarter)(
4910
+ safeEndDate ?? /* @__PURE__ */ new Date()
4911
+ )}/${(safeEndDate?.getFullYear() ?? 0) + 543}` }),
4912
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("button", { className: "rounded-md subtitile-1 flex gap-2 align-start", children: [
4913
+ statusIcon,
4914
+ statusLabel
4915
+ ] })
4926
4916
  ]
4927
4917
  },
4928
4918
  element.id
@@ -4937,42 +4927,52 @@ var RowOverlay = ({ data, barHeight, barSpacing, totalHeaderHeight }) => /* @__P
4937
4927
  left: 0,
4938
4928
  right: 0,
4939
4929
  height: `${data.length * (barHeight + barSpacing)}px`,
4940
- pointerEvents: "none",
4941
- zIndex: 5
4930
+ pointerEvents: "none"
4942
4931
  },
4943
- children: data.map((d, i) => {
4932
+ children: data.map((_, i) => {
4944
4933
  if (i === 0) return null;
4934
+ console.log("rendering row line", i);
4945
4935
  const yPos = i * (barHeight + barSpacing) - barSpacing / 2;
4946
4936
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4947
4937
  "div",
4948
4938
  {
4939
+ className: "",
4949
4940
  style: {
4950
4941
  position: "absolute",
4951
4942
  top: `${yPos}px`,
4952
4943
  left: 0,
4953
4944
  right: 0,
4954
4945
  height: "1px",
4955
- backgroundColor: "#d0d0d0"
4946
+ backgroundColor: "#E9E9E9"
4956
4947
  }
4957
4948
  },
4958
- `row-line-${d.id}`
4949
+ `row-line-${i}`
4959
4950
  );
4960
4951
  })
4961
4952
  }
4962
4953
  );
4963
- var GanttChart = ({ data, width, height }) => {
4954
+ var GanttChart = ({
4955
+ data,
4956
+ width,
4957
+ mode
4958
+ }) => {
4964
4959
  const svgRef = (0, import_react24.useRef)(null);
4965
4960
  const leftPanelRef = (0, import_react24.useRef)(null);
4966
4961
  const dataContainerRef = (0, import_react24.useRef)(null);
4967
4962
  const [viewMode] = (0, import_react24.useState)("year");
4968
- const { barHeight, barSpacing, headersGroupLayer1Height, headersGroupLayer2Height } = LAYOUT;
4963
+ const {
4964
+ barHeight,
4965
+ barSpacing,
4966
+ headersGroupLayer1Height,
4967
+ headersGroupLayer2Height
4968
+ } = LAYOUT;
4969
4969
  const totalHeaderHeight = headersGroupLayer1Height + headersGroupLayer2Height;
4970
4970
  (0, import_react24.useEffect)(() => {
4971
4971
  if (!data || !svgRef.current) return;
4972
4972
  const margin = { top: 0, right: 20, bottom: 20, left: 20 };
4973
4973
  const chartHeight = data.length * (barHeight + barSpacing) + margin.top + margin.bottom;
4974
4974
  const containerWidth = width * 2;
4975
- const containerHeight = totalHeaderHeight + chartHeight;
4975
+ const containerHeight = totalHeaderHeight + chartHeight > 590 ? totalHeaderHeight + chartHeight : 590;
4976
4976
  const borderRadius = 5;
4977
4977
  if (leftPanelRef.current) {
4978
4978
  leftPanelRef.current.style.height = `${containerHeight}px`;
@@ -4985,23 +4985,31 @@ var GanttChart = ({ data, width, height }) => {
4985
4985
  const chartGroup = svg.append("g").attr("transform", `translate(${margin.left}, ${totalHeaderHeight})`);
4986
4986
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
4987
4987
  const domainStart = (0, import_date_fns3.startOfDay)((0, import_date_fns3.startOfYear)(new Date(currentYear, 0, 1)));
4988
- const domainEnd = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)((0, import_date_fns3.endOfYear)(new Date(currentYear, 0, 1)), 1));
4988
+ const domainEnd = (0, import_date_fns3.startOfDay)(
4989
+ (0, import_date_fns3.addDays)((0, import_date_fns3.endOfYear)(new Date(currentYear, 0, 1)), 1)
4990
+ );
4989
4991
  const xScale = d33.scaleTime().domain([domainStart, domainEnd]).range([0, containerWidth - margin.left - margin.right]);
4990
4992
  const buildTimeBuckets = (domain) => ({
4991
4993
  uniqueYears: d33.timeYear.every(1)?.range(domain[0], domain[1]) || [],
4992
4994
  uniqueMonths: d33.timeMonth.every(1)?.range(domain[0], domain[1]) || [],
4993
- uniqueWeeks: (0, import_date_fns3.eachWeekOfInterval)({ start: domain[0], end: domain[1] }, { weekStartsOn: 1 }),
4994
- uniqueDays: d33.timeDay.range((0, import_date_fns3.startOfDay)(domain[0]), (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(domain[1], 1))) || []
4995
+ uniqueWeeks: (0, import_date_fns3.eachWeekOfInterval)(
4996
+ { start: domain[0], end: domain[1] },
4997
+ { weekStartsOn: 1 }
4998
+ ),
4999
+ uniqueDays: d33.timeDay.range(
5000
+ (0, import_date_fns3.startOfDay)(domain[0]),
5001
+ (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(domain[1], 1))
5002
+ ) || []
4995
5003
  });
4996
5004
  const renderYearHeaders = (layer1, layer2, newXScale, buckets) => {
4997
5005
  layer1.selectAll(".year-bg").data(buckets.uniqueYears).enter().append("rect").attr("class", "year-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
4998
5006
  const nextYearStart = (0, import_date_fns3.startOfDay)(new Date(d.getFullYear() + 1, 0, 1));
4999
5007
  return newXScale(nextYearStart) - newXScale(d);
5000
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5008
+ }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#E9E9E9").style("stroke-width", 1);
5001
5009
  layer1.selectAll(".year-label").data(buckets.uniqueYears).enter().append("text").attr("class", "year-label").attr("x", (d) => {
5002
5010
  const nextYear = new Date(d.getFullYear() + 1, 0, 1);
5003
5011
  return newXScale(d) + (newXScale(nextYear) - newXScale(d)) / 2;
5004
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `${d.getFullYear() + 543}`);
5012
+ }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1 + 2}px`).style("font-weight", "regular").style("fill", "#000").text((d) => `${d.getFullYear() + 543}`);
5005
5013
  const quarters2 = [];
5006
5014
  buckets.uniqueYears.forEach((year) => {
5007
5015
  for (let q = 0; q < 4; q++) {
@@ -5009,75 +5017,36 @@ var GanttChart = ({ data, width, height }) => {
5009
5017
  }
5010
5018
  });
5011
5019
  layer2.selectAll(".quarter-bg").data(quarters2).enter().append("rect").attr("class", "quarter-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
5012
- const nextQuarter = (0, import_date_fns3.startOfDay)(new Date(d.getFullYear(), d.getMonth() + 3, 1));
5020
+ const nextQuarter = (0, import_date_fns3.startOfDay)(
5021
+ new Date(d.getFullYear(), d.getMonth() + 3, 1)
5022
+ );
5013
5023
  return newXScale(nextQuarter) - newXScale(d);
5014
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5024
+ }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#E9E9E9").style("stroke-width", 1);
5015
5025
  layer2.selectAll(".quarter-label").data(quarters2).enter().append("text").attr("class", "quarter-label").attr("x", (d) => {
5016
- const nextQuarter = (0, import_date_fns3.startOfDay)(new Date(d.getFullYear(), d.getMonth() + 3, 1));
5026
+ const nextQuarter = (0, import_date_fns3.startOfDay)(
5027
+ new Date(d.getFullYear(), d.getMonth() + 3, 1)
5028
+ );
5017
5029
  return newXScale(d) + (newXScale(nextQuarter) - newXScale(d)) / 2;
5018
- }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").text((d) => `\u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A ${Math.floor(d.getMonth() / 3) + 1}`);
5019
- };
5020
- const renderMonthHeaders = (layer1, layer2, newXScale, buckets) => {
5021
- layer1.selectAll(".month-bg").data(buckets.uniqueMonths).enter().append("rect").attr("class", "month-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
5022
- const nextMonth = (0, import_date_fns3.startOfDay)(new Date(d.getFullYear(), d.getMonth() + 1, 1));
5023
- return newXScale(nextMonth) - newXScale(d) + 11;
5024
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5025
- layer1.selectAll(".month-label").data(buckets.uniqueMonths).enter().append("text").attr("class", "month-label").attr("x", (d) => {
5026
- const nextMonth = (0, import_date_fns3.startOfDay)(new Date(d.getFullYear(), d.getMonth() + 1, 1));
5027
- return newXScale(d) + (newXScale(nextMonth) - newXScale(d)) / 2;
5028
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `${formatThaiMonth(d)} ${d.getFullYear() + 543}`);
5029
- layer2.selectAll(".week-bg").data(buckets.uniqueWeeks).enter().append("rect").attr("class", "week-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
5030
- const weekEnd = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 7));
5031
- return newXScale(weekEnd) - newXScale(d) + 1;
5032
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5033
- layer2.selectAll(".week-label").data(buckets.uniqueWeeks).enter().append("text").attr("class", "week-label").attr("x", (d) => {
5034
- const weekEnd = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 7));
5035
- return newXScale(d) + (newXScale(weekEnd) - newXScale(d)) / 2;
5036
- }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").text((d) => `\u0E2A\u0E31\u0E1B\u0E14\u0E32\u0E2B\u0E4C\u0E17\u0E35\u0E48 ${(0, import_date_fns3.getWeek)(d, { weekStartsOn: 1 })}`);
5037
- };
5038
- const renderWeekHeaders = (layer1, layer2, newXScale, buckets) => {
5039
- layer1.selectAll(".week-bg").data(buckets.uniqueWeeks).enter().append("rect").attr("class", "week-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
5040
- const weekEnd = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 7));
5041
- return newXScale(weekEnd) - newXScale(d);
5042
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5043
- layer1.selectAll(".week-label").data(buckets.uniqueWeeks).enter().append("text").attr("class", "week-label").attr("x", (d) => {
5044
- const weekEnd = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 7));
5045
- return newXScale(d) + (newXScale(weekEnd) - newXScale(d)) / 2;
5046
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `\u0E2A\u0E31\u0E1B\u0E14\u0E32\u0E2B\u0E4C\u0E17\u0E35\u0E48 ${(0, import_date_fns3.getWeek)(d, { weekStartsOn: 1 })}`);
5047
- layer2.selectAll(".day-bg").data(buckets.uniqueDays).enter().append("rect").attr("class", "day-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
5048
- const nextDay = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 1));
5049
- return newXScale(nextDay) - newXScale(d);
5050
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
5051
- layer2.selectAll(".day-of-week").data(buckets.uniqueDays).enter().append("text").attr("class", "day-of-week").attr("x", (d) => {
5052
- const nextDay = (0, import_date_fns3.startOfDay)((0, import_date_fns3.addDays)(d, 1));
5053
- return newXScale(d) + (newXScale(nextDay) - newXScale(d)) / 2;
5054
- }).attr("y", -headersGroupLayer2Height / 2).attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").each(function(d) {
5055
- const textElement = d33.select(this);
5056
- textElement.text("");
5057
- textElement.append("tspan").text(THAI_DAYS[d.getDay()]).attr("x", textElement.attr("x")).attr("dy", "-0.3em");
5058
- textElement.append("tspan").text((0, import_date_fns3.format)(d, "d")).attr("x", textElement.attr("x")).attr("dy", "1.2em");
5059
- });
5030
+ }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2 + 3}px`).style("font-weight", "regular").style("fill", "#000").text((d) => `\u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A ${Math.floor(d.getMonth() / 3) + 1}`);
5060
5031
  };
5061
5032
  const drawHeaders = (layer1, layer2, newXScale, buckets) => {
5062
- if (viewMode === "year") return renderYearHeaders(layer1, layer2, newXScale, buckets);
5063
- if (viewMode === "month") return renderMonthHeaders(layer1, layer2, newXScale, buckets);
5064
- return renderWeekHeaders(layer1, layer2, newXScale, buckets);
5033
+ return renderYearHeaders(layer1, layer2, newXScale, buckets);
5065
5034
  };
5066
- const getGridlineData = (mode, buckets, domain) => {
5067
- if (mode === "year") return buckets.uniqueMonths;
5068
- if (mode === "month") return buckets.uniqueWeeks;
5069
- if (mode === "week") return buckets.uniqueDays;
5035
+ const getGridlineData = (mode2, buckets, domain) => {
5036
+ if (mode2 === "year") return buckets.uniqueMonths;
5037
+ if (mode2 === "month") return buckets.uniqueWeeks;
5038
+ if (mode2 === "week") return buckets.uniqueDays;
5070
5039
  return (0, import_date_fns3.eachHourOfInterval)({ start: domain[0], end: domain[1] });
5071
5040
  };
5072
5041
  const drawGridlines = (group, gridlineData, newXScale) => {
5073
- group.selectAll(".gridline").data(gridlineData).enter().append("line").attr("class", "gridline").attr("x1", (d) => newXScale(d)).attr("x2", (d) => newXScale(d)).attr("y1", 0).attr("y2", chartHeight - margin.top - margin.bottom).attr("stroke", "#000").attr("stroke-width", 1).style("opacity", 0.3);
5042
+ group.selectAll(".gridline").data(gridlineData).enter().append("line").attr("class", "gridline").attr("x1", (d) => newXScale(d)).attr("x2", (d) => newXScale(d)).attr("y1", 0).attr("y2", containerHeight).attr("stroke", "#E9E9E9").attr("stroke-width", 1);
5074
5043
  };
5075
5044
  const drawRowSeparators = (group, getYPosition) => {
5076
5045
  const rowSeparatorGroup = group.append("g").attr("class", "row-separators");
5077
5046
  data.forEach((_d, i) => {
5078
5047
  if (i === 0) return;
5079
5048
  const y = getYPosition(i) - barSpacing / 2;
5080
- rowSeparatorGroup.append("line").attr("x1", 0).attr("x2", containerWidth - margin.left - margin.right).attr("y1", y).attr("y2", y).attr("stroke", "#d0d0d0").attr("stroke-width", 1).style("pointer-events", "none");
5049
+ rowSeparatorGroup.append("line").attr("x1", 0).attr("x2", containerWidth - margin.left - margin.right).attr("y1", y).attr("y2", y).attr("stroke", "#E9E9E9").attr("stroke-width", 1).style("pointer-events", "none");
5081
5050
  });
5082
5051
  rowSeparatorGroup.lower();
5083
5052
  };
@@ -5085,16 +5054,27 @@ var GanttChart = ({ data, width, height }) => {
5085
5054
  const barsGroup = group.append("g").attr("class", "bars-group");
5086
5055
  const renderBarHeight = barHeight;
5087
5056
  const labelPadding = 10;
5088
- barsGroup.selectAll(".bar-background").data(data).enter().append("rect").attr("class", "bar-background").attr("x", (d) => newXScale(getAdjustedStart(d))).attr("y", (_d, i) => getYPosition(i)).attr("height", renderBarHeight).attr("width", (d) => newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d))).attr("fill", (d) => getStatusColor(d.status)).attr("rx", borderRadius).attr("ry", borderRadius);
5089
- barsGroup.selectAll(".bar-head").data(data).enter().append("path").attr("class", "bar-head").attr("fill", (d) => d.color).attr("d", (d, i) => {
5090
- const x = newXScale(getAdjustedStart(d));
5091
- const y = getYPosition(i);
5092
- const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5093
- const headWidth = Math.min(barWidth * 0.5, 20);
5094
- return roundedRectPath(x, y, headWidth, renderBarHeight, borderRadius);
5095
- });
5057
+ barsGroup.selectAll(".bar-background").data(data).enter().append("rect").attr("class", "bar-background").attr("x", (d) => newXScale(getAdjustedStart(d))).attr("y", (_d, i) => getYPosition(i)).attr("height", renderBarHeight).attr(
5058
+ "width",
5059
+ (d) => newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d))
5060
+ ).attr("fill", (d) => getStatusColor(d.status)).attr("rx", borderRadius).attr("ry", borderRadius);
5061
+ {
5062
+ mode === "project" && barsGroup.selectAll(".bar-head").data(data).enter().append("path").attr("class", "bar-head").attr("fill", (d) => d.color).attr("d", (d, i) => {
5063
+ const x = newXScale(getAdjustedStart(d));
5064
+ const y = getYPosition(i);
5065
+ const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5066
+ const headWidth = Math.min(barWidth * 0.5, 20);
5067
+ return roundedRectPath(
5068
+ x,
5069
+ y,
5070
+ headWidth,
5071
+ renderBarHeight,
5072
+ borderRadius
5073
+ );
5074
+ });
5075
+ }
5096
5076
  const labels = group.append("g").attr("class", "labels");
5097
- const labelSelection = labels.selectAll(".label").data(data).enter().append("text").attr("class", "label").attr("y", (_d, i) => getYPosition(i) + renderBarHeight / 2).attr("dy", "0.35em").text((d) => d.label).style("fill", "black").style("font-size", "12px").style("pointer-events", "none");
5077
+ const labelSelection = labels.selectAll(".label").data(data).enter().append("text").attr("class", "label").attr("y", (_d, i) => getYPosition(i) + renderBarHeight / 2).attr("dy", "0.35em").text((d) => d.label).style("fill", "black").style("font-weight", "400").style("pointer-events", "none");
5098
5078
  labelSelection.each(function(d) {
5099
5079
  const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5100
5080
  const headWidth = Math.min(barWidth * 0.5, 20);
@@ -5117,8 +5097,17 @@ var GanttChart = ({ data, width, height }) => {
5117
5097
  const timeBuckets = buildTimeBuckets(newXScale.domain());
5118
5098
  const headersGroupLayer1 = chartGroup.append("g");
5119
5099
  const headersGroupLayer2 = chartGroup.append("g");
5120
- drawHeaders(headersGroupLayer1, headersGroupLayer2, newXScale, timeBuckets);
5121
- const gridlineData = getGridlineData(viewMode, timeBuckets, newXScale.domain());
5100
+ drawHeaders(
5101
+ headersGroupLayer1,
5102
+ headersGroupLayer2,
5103
+ newXScale,
5104
+ timeBuckets
5105
+ );
5106
+ const gridlineData = getGridlineData(
5107
+ viewMode,
5108
+ timeBuckets,
5109
+ newXScale.domain()
5110
+ );
5122
5111
  drawGridlines(headersGroupLayer2, gridlineData, newXScale);
5123
5112
  drawRowSeparators(chartGroup, getYPosition);
5124
5113
  drawBarsAndLabels(chartGroup, newXScale, getYPosition);
@@ -5136,7 +5125,6 @@ var GanttChart = ({ data, width, height }) => {
5136
5125
  }, [
5137
5126
  data,
5138
5127
  width,
5139
- height,
5140
5128
  viewMode,
5141
5129
  barHeight,
5142
5130
  barSpacing,
@@ -5147,13 +5135,13 @@ var GanttChart = ({ data, width, height }) => {
5147
5135
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5148
5136
  "div",
5149
5137
  {
5138
+ className: "body-1",
5150
5139
  style: {
5151
5140
  display: "flex",
5152
5141
  flexDirection: "column",
5153
- padding: "20px",
5154
5142
  width: `${width}px`,
5155
- height: `${height}px`,
5156
- border: "1px solid #ccc",
5143
+ height: `590px`,
5144
+ border: "1px solid #E9E9E9",
5157
5145
  borderRadius: "10px",
5158
5146
  backgroundColor: "#fff",
5159
5147
  overflow: "hidden"
@@ -5169,49 +5157,69 @@ var GanttChart = ({ data, width, height }) => {
5169
5157
  position: "relative"
5170
5158
  },
5171
5159
  children: [
5172
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RowOverlay, { data, barHeight, barSpacing, totalHeaderHeight }),
5160
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "z-1", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5161
+ RowOverlay,
5162
+ {
5163
+ data: data.length > 10 ? data : ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
5164
+ barHeight,
5165
+ barSpacing,
5166
+ totalHeaderHeight
5167
+ }
5168
+ ) }),
5173
5169
  /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
5174
5170
  "div",
5175
5171
  {
5176
5172
  ref: leftPanelRef,
5173
+ className: "border-r",
5177
5174
  style: {
5178
5175
  width: "520px",
5179
5176
  minWidth: "500px",
5180
5177
  display: "flex",
5181
5178
  flexDirection: "column",
5182
5179
  backgroundColor: "#fff",
5183
- borderRight: "1px solid #ddd",
5184
5180
  zIndex: 2
5185
5181
  },
5186
5182
  children: [
5187
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
5188
- "div",
5189
- {
5190
- style: {
5191
- display: "grid",
5192
- gridTemplateColumns: "200px 100px 100px 100px",
5193
- fontSize: "12px",
5194
- fontWeight: "bold",
5195
- color: "#666",
5196
- backgroundColor: "#fafafa",
5197
- borderBottom: "2px solid #ddd",
5198
- padding: "0 8px",
5199
- height: `${totalHeaderHeight}px`,
5200
- marginBottom: "10px",
5201
- position: "sticky",
5202
- top: 0,
5203
- alignItems: "center",
5204
- boxSizing: "border-box"
5183
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { ref: dataContainerRef, children: [
5184
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
5185
+ "div",
5186
+ {
5187
+ className: "grid body-2 grid-cols-[1fr_100px_130px] gap-2 px-8 border-b bg-white",
5188
+ style: {
5189
+ height: `${totalHeaderHeight}px`,
5190
+ marginBottom: "10px",
5191
+ position: "sticky",
5192
+ top: 0,
5193
+ alignItems: "center",
5194
+ zIndex: 5
5195
+ },
5196
+ children: [
5197
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5198
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E2A\u0E48\u0E07" }),
5199
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E2A\u0E16\u0E32\u0E19\u0E30" })
5200
+ ]
5201
+ }
5202
+ ),
5203
+ data.map((element) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5204
+ ProjectRow,
5205
+ {
5206
+ mode,
5207
+ element,
5208
+ barHeight,
5209
+ barSpacing
5205
5210
  },
5206
- children: [
5207
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5208
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E27\u0E31\u0E19\u0E40\u0E23\u0E34\u0E48\u0E21" }),
5209
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E2A\u0E48\u0E07" }),
5210
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { children: "\u0E2A\u0E16\u0E32\u0E19\u0E30" })
5211
- ]
5211
+ element.id
5212
+ ))
5213
+ ] }),
5214
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "z-3", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5215
+ RowOverlay,
5216
+ {
5217
+ data,
5218
+ barHeight,
5219
+ barSpacing,
5220
+ totalHeaderHeight
5212
5221
  }
5213
- ),
5214
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { ref: dataContainerRef, children: data.map((element) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ProjectRow, { element, barHeight, barSpacing }, element.id)) })
5222
+ ) })
5215
5223
  ]
5216
5224
  }
5217
5225
  ),
@@ -5246,7 +5254,7 @@ var GanttChart = ({ data, width, height }) => {
5246
5254
  };
5247
5255
 
5248
5256
  // src/CardKPI/CardKPI/CardKPI.tsx
5249
- var import_icons_react15 = require("@tabler/icons-react");
5257
+ var import_icons_react16 = require("@tabler/icons-react");
5250
5258
  var import_react25 = require("react");
5251
5259
  var import_jsx_runtime49 = require("react/jsx-runtime");
5252
5260
  function KPIRow({ item }) {
@@ -5257,7 +5265,7 @@ function KPIRow({ item }) {
5257
5265
  children: [
5258
5266
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "line-clamp-2", children: item.textValue }),
5259
5267
  item.inputType === "NUMBER" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex", children: `${item.currentValue}/${item.numberValue} ${item.unit}` }),
5260
- item.inputType === "NUMBER" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ProgressBar, { percent: Math.floor(item.currentValue * 100 / (item.numberValue ?? 1)), type: "circle", checkpoints: [0] }) }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_jsx_runtime49.Fragment, { children: item.currentValue !== 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_icons_react15.IconCheckbox, { className: "text-green-500 flex justify-center w-full", size: 30 }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_icons_react15.IconSquare, { className: "text-gray-200 flex justify-center w-full", size: 30 }) })
5268
+ item.inputType === "NUMBER" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ProgressBar, { percent: Math.floor(item.currentValue * 100 / (item.numberValue ?? 1)), type: "circle", checkpoints: [0] }) }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_jsx_runtime49.Fragment, { children: item.currentValue !== 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_icons_react16.IconCheckbox, { className: "text-green-500 flex justify-center w-full", size: 30 }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_icons_react16.IconSquare, { className: "text-gray-200 flex justify-center w-full", size: 30 }) })
5261
5269
  ]
5262
5270
  }
5263
5271
  );
@@ -5293,7 +5301,7 @@ function CardKPI({
5293
5301
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ProgressBar, { percent: overallPercent, type: "line", checkpoints: [0] })
5294
5302
  ] }),
5295
5303
  /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "border-b", children: [
5296
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "body-2 ", children: "\u0E15\u0E31\u0E27\u0E0A\u0E35\u0E49\u0E27\u0E31\u0E14\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C" }),
5304
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "body-2 ", children: "\u0E01\u0E25\u0E38\u0E48\u0E21\u0E40\u0E1B\u0E49\u0E32\u0E2B\u0E21\u0E32\u0E22" }),
5297
5305
  indicator.filter((ind) => ind.indicatorType === "TARGET").map((item, index) => {
5298
5306
  if (index === 2) return;
5299
5307
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(KPIRow, { item });
@@ -5306,9 +5314,8 @@ function CardKPI({
5306
5314
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(KPIRow, { item });
5307
5315
  })
5308
5316
  ] }),
5309
- indicator.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "text-sm text-gray-500 italic", children: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5310
5317
  indicator.filter((item) => item.indicatorType === "TARGET").length > 2 || indicator.filter((item) => item.indicatorType === "OUTPUT").length > 2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "bottom-0 right-1/2 absolute text-gray-300", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
5311
- import_icons_react15.IconDots,
5318
+ import_icons_react16.IconDots,
5312
5319
  {
5313
5320
  className: "cursor-pointer",
5314
5321
  onClick: () => setIsOpen(true)