@j3m-quantum/ui 1.11.2 → 2.1.0
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/README.md +72 -7
- package/cursor-rules-for-consumers.md +24 -15
- package/dist/cli/index.js +670 -0
- package/dist/cli/postinstall.js +25 -0
- package/dist/index.cjs +2443 -624
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +213 -31
- package/dist/index.d.ts +213 -31
- package/dist/index.js +2440 -626
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
package/dist/index.cjs
CHANGED
|
@@ -123,6 +123,53 @@ function useIsMobile() {
|
|
|
123
123
|
function cn(...inputs) {
|
|
124
124
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
125
125
|
}
|
|
126
|
+
var statusCellFillClasses = {
|
|
127
|
+
// Green - complete/valid/ready state
|
|
128
|
+
complete: {
|
|
129
|
+
bg: "bg-green-50/50 dark:bg-green-950/30"},
|
|
130
|
+
ready: {
|
|
131
|
+
combined: "border-l-[3px] border-l-green-500 bg-green-50/50 dark:bg-green-950/30"
|
|
132
|
+
},
|
|
133
|
+
// Amber - warning/attention state
|
|
134
|
+
warning: {
|
|
135
|
+
bg: "bg-amber-50/50 dark:bg-amber-950/30"},
|
|
136
|
+
// Red - critical/risk state
|
|
137
|
+
critical: {
|
|
138
|
+
bg: "bg-red-50/50 dark:bg-red-950/30"},
|
|
139
|
+
risk: {
|
|
140
|
+
combined: "border-l-[3px] border-l-red-500 bg-red-50/50 dark:bg-red-950/30"
|
|
141
|
+
},
|
|
142
|
+
// Grey - normal/pending/neutral state (on track but not complete)
|
|
143
|
+
normal: {
|
|
144
|
+
combined: "border-l-[3px] border-l-muted-foreground/40 bg-muted/30 dark:bg-muted/20"
|
|
145
|
+
},
|
|
146
|
+
// Shipped - distinct muted state with green accent (greyed out + check)
|
|
147
|
+
shipped: {
|
|
148
|
+
combined: "border-l-[3px] border-l-green-500/50 bg-muted/50 dark:bg-muted/30"
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
var statusCellTextClasses = {
|
|
152
|
+
ready: {
|
|
153
|
+
title: "text-foreground",
|
|
154
|
+
subtitle: "text-green-700/80 dark:text-green-300/80",
|
|
155
|
+
icon: "text-green-600 dark:text-green-400"
|
|
156
|
+
},
|
|
157
|
+
risk: {
|
|
158
|
+
title: "text-foreground",
|
|
159
|
+
subtitle: "text-red-700/80 dark:text-red-300/80",
|
|
160
|
+
icon: "text-red-600 dark:text-red-400"
|
|
161
|
+
},
|
|
162
|
+
normal: {
|
|
163
|
+
title: "text-foreground",
|
|
164
|
+
subtitle: "text-muted-foreground",
|
|
165
|
+
icon: "text-muted-foreground"
|
|
166
|
+
},
|
|
167
|
+
shipped: {
|
|
168
|
+
title: "text-muted-foreground",
|
|
169
|
+
subtitle: "text-muted-foreground/70",
|
|
170
|
+
icon: "text-green-600/70 dark:text-green-400/70"
|
|
171
|
+
}
|
|
172
|
+
};
|
|
126
173
|
var buttonVariants = classVarianceAuthority.cva(
|
|
127
174
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
128
175
|
{
|
|
@@ -1597,6 +1644,166 @@ function FieldError({
|
|
|
1597
1644
|
}
|
|
1598
1645
|
);
|
|
1599
1646
|
}
|
|
1647
|
+
var iconMap = {
|
|
1648
|
+
factory: lucideReact.Factory,
|
|
1649
|
+
truck: lucideReact.Truck,
|
|
1650
|
+
check: lucideReact.Check,
|
|
1651
|
+
alert: lucideReact.AlertTriangle,
|
|
1652
|
+
trending: lucideReact.TrendingUp
|
|
1653
|
+
};
|
|
1654
|
+
var statusColorMap = {
|
|
1655
|
+
normal: "text-muted-foreground",
|
|
1656
|
+
success: "text-green-600 dark:text-green-400",
|
|
1657
|
+
warning: "text-amber-600 dark:text-amber-400",
|
|
1658
|
+
critical: "text-red-600 dark:text-red-400"
|
|
1659
|
+
};
|
|
1660
|
+
function InsightBar({ metrics, className }) {
|
|
1661
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1662
|
+
"div",
|
|
1663
|
+
{
|
|
1664
|
+
"data-slot": "insight-bar",
|
|
1665
|
+
className: cn(
|
|
1666
|
+
"flex flex-wrap items-center gap-6 px-4 py-3",
|
|
1667
|
+
"border-b border-border bg-muted/20",
|
|
1668
|
+
className
|
|
1669
|
+
),
|
|
1670
|
+
children: metrics.map((metric) => {
|
|
1671
|
+
const Icon2 = metric.icon ? iconMap[metric.icon] : null;
|
|
1672
|
+
const statusColor = metric.status ? statusColorMap[metric.status] : "text-foreground";
|
|
1673
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1674
|
+
"div",
|
|
1675
|
+
{
|
|
1676
|
+
className: "flex items-center gap-2",
|
|
1677
|
+
children: [
|
|
1678
|
+
Icon2 && /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: cn("h-4 w-4", statusColor) }),
|
|
1679
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1680
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
1681
|
+
"text-lg font-semibold tabular-nums",
|
|
1682
|
+
statusColor
|
|
1683
|
+
), children: metric.isPercentage ? `${Math.round(metric.value)}%` : metric.value.toLocaleString(void 0, { maximumFractionDigits: 1 }) }),
|
|
1684
|
+
metric.unit && !metric.isPercentage && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: metric.unit }),
|
|
1685
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: metric.label })
|
|
1686
|
+
] })
|
|
1687
|
+
]
|
|
1688
|
+
},
|
|
1689
|
+
metric.key
|
|
1690
|
+
);
|
|
1691
|
+
})
|
|
1692
|
+
}
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
var iconMap2 = {
|
|
1696
|
+
factory: lucideReact.Factory,
|
|
1697
|
+
truck: lucideReact.Truck,
|
|
1698
|
+
check: lucideReact.Check
|
|
1699
|
+
};
|
|
1700
|
+
var statusBgMap = {
|
|
1701
|
+
normal: "bg-muted/30",
|
|
1702
|
+
complete: statusCellFillClasses.complete.bg,
|
|
1703
|
+
warning: statusCellFillClasses.warning.bg,
|
|
1704
|
+
critical: statusCellFillClasses.critical.bg
|
|
1705
|
+
};
|
|
1706
|
+
var statusTextMap = {
|
|
1707
|
+
normal: "text-muted-foreground",
|
|
1708
|
+
complete: "text-green-700 dark:text-green-300",
|
|
1709
|
+
warning: "text-amber-700 dark:text-amber-300",
|
|
1710
|
+
critical: "text-red-700 dark:text-red-300"
|
|
1711
|
+
};
|
|
1712
|
+
function ColumnSummaryCell({
|
|
1713
|
+
data,
|
|
1714
|
+
widthClass = "min-w-[120px]",
|
|
1715
|
+
className
|
|
1716
|
+
}) {
|
|
1717
|
+
const status = data.status || "normal";
|
|
1718
|
+
const bgClass = statusBgMap[status];
|
|
1719
|
+
const textClass = statusTextMap[status];
|
|
1720
|
+
const isClickable = !!data.onClick;
|
|
1721
|
+
const PrimaryIcon = data.primary?.icon ? iconMap2[data.primary.icon] : null;
|
|
1722
|
+
const SecondaryIcon = data.secondary?.icon ? iconMap2[data.secondary.icon] : null;
|
|
1723
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1724
|
+
"div",
|
|
1725
|
+
{
|
|
1726
|
+
role: isClickable ? "button" : void 0,
|
|
1727
|
+
tabIndex: isClickable ? 0 : void 0,
|
|
1728
|
+
onClick: data.onClick,
|
|
1729
|
+
onKeyDown: (e) => {
|
|
1730
|
+
if (isClickable && (e.key === "Enter" || e.key === " ")) {
|
|
1731
|
+
e.preventDefault();
|
|
1732
|
+
data.onClick?.();
|
|
1733
|
+
}
|
|
1734
|
+
},
|
|
1735
|
+
className: cn(
|
|
1736
|
+
// Base sizing
|
|
1737
|
+
widthClass,
|
|
1738
|
+
"flex flex-col gap-0.5 px-2 py-1.5",
|
|
1739
|
+
// Background based on status
|
|
1740
|
+
bgClass,
|
|
1741
|
+
// Clickable styles
|
|
1742
|
+
isClickable && "cursor-pointer hover:brightness-95 transition-all",
|
|
1743
|
+
isClickable && "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
1744
|
+
className
|
|
1745
|
+
),
|
|
1746
|
+
children: [
|
|
1747
|
+
data.primary && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
1748
|
+
PrimaryIcon && /* @__PURE__ */ jsxRuntime.jsx(PrimaryIcon, { className: cn("h-3 w-3", textClass) }),
|
|
1749
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs font-medium tabular-nums", textClass), children: data.primary.value.toLocaleString(void 0, { maximumFractionDigits: 1 }) }),
|
|
1750
|
+
data.primary.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: data.primary.unit })
|
|
1751
|
+
] }),
|
|
1752
|
+
data.secondary && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
1753
|
+
SecondaryIcon && /* @__PURE__ */ jsxRuntime.jsx(SecondaryIcon, { className: cn("h-3 w-3 text-muted-foreground") }),
|
|
1754
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground tabular-nums", children: [
|
|
1755
|
+
data.secondary.value.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
1756
|
+
data.secondary.unit && ` ${data.secondary.unit}`
|
|
1757
|
+
] })
|
|
1758
|
+
] }),
|
|
1759
|
+
data.tertiary && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground/70 tabular-nums", children: [
|
|
1760
|
+
data.tertiary.value.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
1761
|
+
data.tertiary.unit && ` ${data.tertiary.unit}`
|
|
1762
|
+
] }) })
|
|
1763
|
+
]
|
|
1764
|
+
}
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
function ColumnSummaryStrip({
|
|
1768
|
+
columns,
|
|
1769
|
+
columnWidthClass = "min-w-[120px]",
|
|
1770
|
+
rowHeaderLabel,
|
|
1771
|
+
rowHeaderWidthClass = "min-w-[200px] w-[200px]",
|
|
1772
|
+
className
|
|
1773
|
+
}) {
|
|
1774
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1775
|
+
"div",
|
|
1776
|
+
{
|
|
1777
|
+
"data-slot": "column-summary-strip",
|
|
1778
|
+
className: cn(
|
|
1779
|
+
"flex border-b border-border",
|
|
1780
|
+
className
|
|
1781
|
+
),
|
|
1782
|
+
children: [
|
|
1783
|
+
rowHeaderLabel !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1784
|
+
"div",
|
|
1785
|
+
{
|
|
1786
|
+
className: cn(
|
|
1787
|
+
"flex items-center px-3 py-1.5",
|
|
1788
|
+
"bg-muted/30 border-r border-border",
|
|
1789
|
+
"sticky left-0 z-10",
|
|
1790
|
+
rowHeaderWidthClass
|
|
1791
|
+
),
|
|
1792
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide", children: rowHeaderLabel })
|
|
1793
|
+
}
|
|
1794
|
+
),
|
|
1795
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1796
|
+
ColumnSummaryCell,
|
|
1797
|
+
{
|
|
1798
|
+
data: column,
|
|
1799
|
+
widthClass: columnWidthClass
|
|
1800
|
+
},
|
|
1801
|
+
column.columnKey
|
|
1802
|
+
)) })
|
|
1803
|
+
]
|
|
1804
|
+
}
|
|
1805
|
+
);
|
|
1806
|
+
}
|
|
1600
1807
|
var cardVariants = classVarianceAuthority.cva(
|
|
1601
1808
|
"rounded-xl text-card-foreground",
|
|
1602
1809
|
{
|
|
@@ -3459,6 +3666,144 @@ function CircularProgress({
|
|
|
3459
3666
|
}
|
|
3460
3667
|
);
|
|
3461
3668
|
}
|
|
3669
|
+
function getVariantFromProgress(value) {
|
|
3670
|
+
if (value >= 100) return "complete";
|
|
3671
|
+
if (value >= 50) return "normal";
|
|
3672
|
+
if (value > 0) return "warning";
|
|
3673
|
+
return "critical";
|
|
3674
|
+
}
|
|
3675
|
+
function getStatusColors(variant) {
|
|
3676
|
+
switch (variant) {
|
|
3677
|
+
case "complete":
|
|
3678
|
+
return {
|
|
3679
|
+
track: "bg-green-500/20 dark:bg-green-500/10",
|
|
3680
|
+
fill: "bg-green-500",
|
|
3681
|
+
text: "text-green-600 dark:text-green-400",
|
|
3682
|
+
icon: "text-green-600 dark:text-green-400"
|
|
3683
|
+
};
|
|
3684
|
+
case "normal":
|
|
3685
|
+
return {
|
|
3686
|
+
track: "bg-green-500/20 dark:bg-green-500/10",
|
|
3687
|
+
fill: "bg-green-500",
|
|
3688
|
+
text: "text-green-600 dark:text-green-400",
|
|
3689
|
+
icon: "text-green-600 dark:text-green-400"
|
|
3690
|
+
};
|
|
3691
|
+
case "warning":
|
|
3692
|
+
return {
|
|
3693
|
+
track: "bg-amber-500/20 dark:bg-amber-500/10",
|
|
3694
|
+
fill: "bg-amber-500",
|
|
3695
|
+
text: "text-amber-600 dark:text-amber-400",
|
|
3696
|
+
icon: "text-amber-600 dark:text-amber-400"
|
|
3697
|
+
};
|
|
3698
|
+
case "critical":
|
|
3699
|
+
return {
|
|
3700
|
+
track: "bg-red-500/20 dark:bg-red-500/10",
|
|
3701
|
+
fill: "bg-red-500",
|
|
3702
|
+
text: "text-red-600 dark:text-red-400",
|
|
3703
|
+
icon: "text-red-600 dark:text-red-400"
|
|
3704
|
+
};
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
function getSizeClasses(size) {
|
|
3708
|
+
switch (size) {
|
|
3709
|
+
case "sm":
|
|
3710
|
+
return {
|
|
3711
|
+
bar: "h-1",
|
|
3712
|
+
text: "text-[10px]",
|
|
3713
|
+
icon: "h-3 w-3",
|
|
3714
|
+
gap: "gap-1"
|
|
3715
|
+
};
|
|
3716
|
+
case "lg":
|
|
3717
|
+
return {
|
|
3718
|
+
bar: "h-3",
|
|
3719
|
+
text: "text-sm",
|
|
3720
|
+
icon: "h-5 w-5",
|
|
3721
|
+
gap: "gap-3"
|
|
3722
|
+
};
|
|
3723
|
+
default:
|
|
3724
|
+
return {
|
|
3725
|
+
bar: "h-2",
|
|
3726
|
+
text: "text-xs",
|
|
3727
|
+
icon: "h-4 w-4",
|
|
3728
|
+
gap: "gap-2"
|
|
3729
|
+
};
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
function StatusProgress({
|
|
3733
|
+
className,
|
|
3734
|
+
value,
|
|
3735
|
+
currentCount,
|
|
3736
|
+
totalCount,
|
|
3737
|
+
unitLabel = "elements",
|
|
3738
|
+
showLabel = false,
|
|
3739
|
+
showCheckmark = true,
|
|
3740
|
+
size = "md",
|
|
3741
|
+
variant,
|
|
3742
|
+
...props
|
|
3743
|
+
}) {
|
|
3744
|
+
const clampedValue = Math.min(100, Math.max(0, value));
|
|
3745
|
+
const isComplete = clampedValue >= 100;
|
|
3746
|
+
const resolvedVariant = variant ?? getVariantFromProgress(clampedValue);
|
|
3747
|
+
const colors = getStatusColors(resolvedVariant);
|
|
3748
|
+
const sizes = getSizeClasses(size);
|
|
3749
|
+
const labelText = React27__namespace.useMemo(() => {
|
|
3750
|
+
if (currentCount !== void 0 && totalCount !== void 0) {
|
|
3751
|
+
return `${currentCount} / ${totalCount} ${unitLabel}`;
|
|
3752
|
+
}
|
|
3753
|
+
return `${Math.round(clampedValue)}%`;
|
|
3754
|
+
}, [currentCount, totalCount, unitLabel, clampedValue]);
|
|
3755
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3756
|
+
"div",
|
|
3757
|
+
{
|
|
3758
|
+
"data-slot": "status-progress",
|
|
3759
|
+
"data-value": clampedValue,
|
|
3760
|
+
"data-variant": resolvedVariant,
|
|
3761
|
+
"data-complete": isComplete,
|
|
3762
|
+
className: cn("flex flex-col w-full", sizes.gap, className),
|
|
3763
|
+
...props,
|
|
3764
|
+
children: [
|
|
3765
|
+
showLabel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between", sizes.gap), children: [
|
|
3766
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-medium", sizes.text, colors.text), children: isComplete && showCheckmark ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
|
|
3767
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn(sizes.icon, colors.icon) }),
|
|
3768
|
+
"Complete"
|
|
3769
|
+
] }) : labelText }),
|
|
3770
|
+
!isComplete && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("tabular-nums text-muted-foreground", sizes.text), children: [
|
|
3771
|
+
Math.round(clampedValue),
|
|
3772
|
+
"%"
|
|
3773
|
+
] })
|
|
3774
|
+
] }),
|
|
3775
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3776
|
+
"div",
|
|
3777
|
+
{
|
|
3778
|
+
className: cn(
|
|
3779
|
+
"w-full rounded-full overflow-hidden",
|
|
3780
|
+
colors.track,
|
|
3781
|
+
sizes.bar
|
|
3782
|
+
),
|
|
3783
|
+
role: "progressbar",
|
|
3784
|
+
"aria-valuenow": clampedValue,
|
|
3785
|
+
"aria-valuemin": 0,
|
|
3786
|
+
"aria-valuemax": 100,
|
|
3787
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3788
|
+
"div",
|
|
3789
|
+
{
|
|
3790
|
+
className: cn(
|
|
3791
|
+
"h-full rounded-full transition-all duration-300 ease-out",
|
|
3792
|
+
colors.fill
|
|
3793
|
+
),
|
|
3794
|
+
style: { width: `${clampedValue}%` }
|
|
3795
|
+
}
|
|
3796
|
+
)
|
|
3797
|
+
}
|
|
3798
|
+
),
|
|
3799
|
+
!showLabel && isComplete && showCheckmark && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center", sizes.gap), children: [
|
|
3800
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn(sizes.icon, colors.icon) }),
|
|
3801
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-medium", sizes.text, colors.text), children: "Complete" })
|
|
3802
|
+
] })
|
|
3803
|
+
]
|
|
3804
|
+
}
|
|
3805
|
+
);
|
|
3806
|
+
}
|
|
3462
3807
|
function TooltipProvider({
|
|
3463
3808
|
delayDuration = 0,
|
|
3464
3809
|
...props
|
|
@@ -6431,15 +6776,27 @@ function getCombinedRiskLevel(data) {
|
|
|
6431
6776
|
if (productionStatus === "delayed" || hasDeliveryDelayed || data.hasWarning) {
|
|
6432
6777
|
return "warning";
|
|
6433
6778
|
}
|
|
6779
|
+
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6780
|
+
const isProductionComplete = productionProgress >= 100;
|
|
6781
|
+
if (isProductionComplete) {
|
|
6782
|
+
return "complete";
|
|
6783
|
+
}
|
|
6434
6784
|
return "normal";
|
|
6435
6785
|
}
|
|
6436
|
-
function getRowStatus(status) {
|
|
6786
|
+
function getRowStatus(status, progress) {
|
|
6437
6787
|
if (status === "critical") return "critical";
|
|
6438
6788
|
if (status === "delayed") return "warning";
|
|
6789
|
+
if (progress !== void 0 && progress >= 100) return "complete";
|
|
6439
6790
|
return "normal";
|
|
6440
6791
|
}
|
|
6441
6792
|
var statusFillClasses = {
|
|
6442
6793
|
normal: {
|
|
6794
|
+
// Grey/muted for "on track but not complete" - reduces visual noise
|
|
6795
|
+
border: "border-l-[3px] border-l-muted-foreground/40",
|
|
6796
|
+
bg: "bg-muted/30 dark:bg-muted/20"
|
|
6797
|
+
},
|
|
6798
|
+
complete: {
|
|
6799
|
+
// Green for "done/complete" - clear success signal
|
|
6443
6800
|
border: "border-l-[3px] border-l-green-500",
|
|
6444
6801
|
bg: "bg-green-50/50 dark:bg-green-950/30"
|
|
6445
6802
|
},
|
|
@@ -6454,6 +6811,13 @@ var statusFillClasses = {
|
|
|
6454
6811
|
};
|
|
6455
6812
|
var statusColors = {
|
|
6456
6813
|
normal: {
|
|
6814
|
+
// Grey/muted for "on track but not complete"
|
|
6815
|
+
icon: "text-muted-foreground",
|
|
6816
|
+
progress: "bg-muted-foreground/60",
|
|
6817
|
+
text: "text-muted-foreground"
|
|
6818
|
+
},
|
|
6819
|
+
complete: {
|
|
6820
|
+
// Green for "done/complete"
|
|
6457
6821
|
icon: "text-green-600 dark:text-green-400",
|
|
6458
6822
|
progress: "bg-green-500",
|
|
6459
6823
|
text: "text-green-700 dark:text-green-300"
|
|
@@ -6481,19 +6845,20 @@ function WeekCell({
|
|
|
6481
6845
|
const combinedRisk = data.type === "data" ? getCombinedRiskLevel(data) : "normal";
|
|
6482
6846
|
const statusClasses = statusFillClasses[combinedRisk];
|
|
6483
6847
|
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6484
|
-
const productionStatus = getRowStatus(data.production?.status);
|
|
6848
|
+
const productionStatus = getRowStatus(data.production?.status, productionProgress);
|
|
6485
6849
|
const productionColors = statusColors[productionStatus];
|
|
6486
6850
|
const deliveryCount = data.deliveries?.length ?? 0;
|
|
6487
|
-
const
|
|
6851
|
+
const allDeliveriesComplete = data.deliveries?.every((d) => (d.progress ?? 0) >= 100) ?? false;
|
|
6852
|
+
const worstDeliveryStatus = data.deliveries?.some((d) => d.status === "critical") ? "critical" : data.deliveries?.some((d) => d.status === "delayed") ? "warning" : allDeliveriesComplete && deliveryCount > 0 ? "complete" : "normal";
|
|
6488
6853
|
const deliveryColors = statusColors[worstDeliveryStatus];
|
|
6489
|
-
const getDeliveryStatusColor = (
|
|
6490
|
-
switch (status) {
|
|
6854
|
+
const getDeliveryStatusColor = (delivery) => {
|
|
6855
|
+
switch (delivery.status) {
|
|
6491
6856
|
case "critical":
|
|
6492
6857
|
return "bg-red-500";
|
|
6493
6858
|
case "delayed":
|
|
6494
6859
|
return "bg-amber-500";
|
|
6495
6860
|
default:
|
|
6496
|
-
return "bg-green-500";
|
|
6861
|
+
return (delivery.progress ?? 0) >= 100 ? "bg-green-500" : "bg-muted-foreground/60";
|
|
6497
6862
|
}
|
|
6498
6863
|
};
|
|
6499
6864
|
const handleClick = () => {
|
|
@@ -6610,24 +6975,18 @@ function WeekCell({
|
|
|
6610
6975
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2014" })
|
|
6611
6976
|
] }),
|
|
6612
6977
|
deliveryCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6613
|
-
data.deliveries?.slice(0, 5).map((delivery, index) =>
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
}
|
|
6626
|
-
) })
|
|
6627
|
-
},
|
|
6628
|
-
delivery.id || index
|
|
6629
|
-
);
|
|
6630
|
-
}),
|
|
6978
|
+
data.deliveries?.slice(0, 5).map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6979
|
+
"div",
|
|
6980
|
+
{
|
|
6981
|
+
className: cn(
|
|
6982
|
+
"flex-1 max-w-[24px] h-1.5 rounded-full",
|
|
6983
|
+
// Solid status color - grey=on-track, green=complete, amber=at-risk, red=critical
|
|
6984
|
+
getDeliveryStatusColor(delivery)
|
|
6985
|
+
),
|
|
6986
|
+
title: delivery.label || `Delivery ${index + 1}`
|
|
6987
|
+
},
|
|
6988
|
+
delivery.id || index
|
|
6989
|
+
)),
|
|
6631
6990
|
deliveryCount > 5 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[8px] text-muted-foreground", children: [
|
|
6632
6991
|
"+",
|
|
6633
6992
|
deliveryCount - 5
|
|
@@ -7241,12 +7600,95 @@ function PlanningTable({
|
|
|
7241
7600
|
}
|
|
7242
7601
|
}
|
|
7243
7602
|
});
|
|
7603
|
+
const insightMetrics = React27__namespace.useMemo(() => {
|
|
7604
|
+
let totalProduced = 0;
|
|
7605
|
+
let totalRequired = 0;
|
|
7606
|
+
let totalDeliveries = 0;
|
|
7607
|
+
for (const supplier of suppliers) {
|
|
7608
|
+
for (const weekKey in supplier.weeks) {
|
|
7609
|
+
const weekData = supplier.weeks[weekKey];
|
|
7610
|
+
if (weekData.production) {
|
|
7611
|
+
totalProduced += weekData.production.produced;
|
|
7612
|
+
totalRequired += weekData.production.target;
|
|
7613
|
+
}
|
|
7614
|
+
totalDeliveries += weekData.deliveries?.length ?? 0;
|
|
7615
|
+
}
|
|
7616
|
+
}
|
|
7617
|
+
const productionPercent = totalRequired > 0 ? totalProduced / totalRequired * 100 : 0;
|
|
7618
|
+
return [
|
|
7619
|
+
{
|
|
7620
|
+
key: "produced",
|
|
7621
|
+
label: "produced",
|
|
7622
|
+
value: totalProduced,
|
|
7623
|
+
unit: "tons",
|
|
7624
|
+
icon: "factory",
|
|
7625
|
+
status: productionPercent >= 100 ? "success" : "normal"
|
|
7626
|
+
},
|
|
7627
|
+
{
|
|
7628
|
+
key: "deliveries",
|
|
7629
|
+
label: "planned deliveries",
|
|
7630
|
+
value: totalDeliveries,
|
|
7631
|
+
icon: "truck",
|
|
7632
|
+
status: "normal"
|
|
7633
|
+
},
|
|
7634
|
+
{
|
|
7635
|
+
key: "progress",
|
|
7636
|
+
label: "produced vs required",
|
|
7637
|
+
value: productionPercent,
|
|
7638
|
+
isPercentage: true,
|
|
7639
|
+
icon: "trending",
|
|
7640
|
+
status: productionPercent >= 100 ? "success" : productionPercent >= 50 ? "normal" : "warning"
|
|
7641
|
+
}
|
|
7642
|
+
];
|
|
7643
|
+
}, [suppliers]);
|
|
7644
|
+
const columnSummaryData = React27__namespace.useMemo(() => {
|
|
7645
|
+
return weeks.map((week) => {
|
|
7646
|
+
const weekKey = getWeekKey(week.startDate);
|
|
7647
|
+
let producedTons = 0;
|
|
7648
|
+
let plannedDeliveries = 0;
|
|
7649
|
+
let sentDeliveries = 0;
|
|
7650
|
+
let hasWarning = false;
|
|
7651
|
+
let hasCritical = false;
|
|
7652
|
+
let allComplete = true;
|
|
7653
|
+
for (const supplier of suppliers) {
|
|
7654
|
+
const weekData = supplier.weeks[weekKey];
|
|
7655
|
+
if (weekData) {
|
|
7656
|
+
if (weekData.production) {
|
|
7657
|
+
producedTons += weekData.production.produced;
|
|
7658
|
+
if (weekData.production.progress !== void 0 && weekData.production.progress < 100) {
|
|
7659
|
+
allComplete = false;
|
|
7660
|
+
}
|
|
7661
|
+
}
|
|
7662
|
+
if (weekData.deliveries) {
|
|
7663
|
+
plannedDeliveries += weekData.deliveries.length;
|
|
7664
|
+
sentDeliveries += weekData.deliveries.filter(
|
|
7665
|
+
(d) => d.status === "on-time" && (d.progress ?? 0) >= 100
|
|
7666
|
+
).length;
|
|
7667
|
+
}
|
|
7668
|
+
if (weekData.hasWarning) hasWarning = true;
|
|
7669
|
+
if (weekData.deliveries?.some((d) => d.status === "critical")) hasCritical = true;
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7672
|
+
let status = "normal";
|
|
7673
|
+
if (hasCritical) status = "critical";
|
|
7674
|
+
else if (hasWarning) status = "warning";
|
|
7675
|
+
else if (allComplete && producedTons > 0) status = "complete";
|
|
7676
|
+
return {
|
|
7677
|
+
weekKey,
|
|
7678
|
+
producedTons,
|
|
7679
|
+
plannedDeliveries,
|
|
7680
|
+
sentDeliveries,
|
|
7681
|
+
status
|
|
7682
|
+
};
|
|
7683
|
+
});
|
|
7684
|
+
}, [weeks, suppliers]);
|
|
7244
7685
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7245
7686
|
"div",
|
|
7246
7687
|
{
|
|
7247
7688
|
"data-slot": "planning-table",
|
|
7248
7689
|
className: cn("flex flex-col gap-4", className),
|
|
7249
7690
|
children: [
|
|
7691
|
+
/* @__PURE__ */ jsxRuntime.jsx(InsightBar, { metrics: insightMetrics }),
|
|
7250
7692
|
showToolbar && /* @__PURE__ */ jsxRuntime.jsx(PlanningTableToolbar, { table }),
|
|
7251
7693
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border bg-background shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7252
7694
|
ScrollArea,
|
|
@@ -7255,37 +7697,80 @@ function PlanningTable({
|
|
|
7255
7697
|
style: { maxHeight },
|
|
7256
7698
|
children: [
|
|
7257
7699
|
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
|
|
7258
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "sticky top-0 z-20", children: [
|
|
7701
|
+
table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7702
|
+
"tr",
|
|
7703
|
+
{
|
|
7704
|
+
children: headerGroup.headers.map((header, index) => {
|
|
7705
|
+
const isCurrentWeekColumn = header.id === currentWeekKey;
|
|
7706
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
|
+
"th",
|
|
7708
|
+
{
|
|
7709
|
+
className: cn(
|
|
7710
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
7711
|
+
"border-r border-b border-border last:border-r-0 bg-sidebar",
|
|
7712
|
+
// First column: sticky with right-edge shadow (Quantum token)
|
|
7713
|
+
index === 0 && stickySupplierColumn && [
|
|
7714
|
+
"sticky left-0 z-30 min-w-[200px]",
|
|
7715
|
+
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7716
|
+
],
|
|
7717
|
+
index > 0 && "min-w-[140px]",
|
|
7718
|
+
// Current week: only highlight text/dot, not full background
|
|
7719
|
+
isCurrentWeekColumn && highlightCurrentWeek && "text-primary"
|
|
7720
|
+
),
|
|
7721
|
+
children: header.isPlaceholder ? null : reactTable.flexRender(
|
|
7722
|
+
header.column.columnDef.header,
|
|
7723
|
+
header.getContext()
|
|
7724
|
+
)
|
|
7725
|
+
},
|
|
7726
|
+
header.id
|
|
7727
|
+
);
|
|
7728
|
+
})
|
|
7729
|
+
},
|
|
7730
|
+
headerGroup.id
|
|
7731
|
+
)),
|
|
7732
|
+
/* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
7733
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: cn(
|
|
7734
|
+
"h-auto px-3 py-1.5 text-left align-middle",
|
|
7735
|
+
"border-r border-b border-border bg-muted/30",
|
|
7736
|
+
stickySupplierColumn && "sticky left-0 z-30 min-w-[200px]",
|
|
7737
|
+
stickySupplierColumn && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7738
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide", children: "Summary" }) }),
|
|
7739
|
+
columnSummaryData.map((summary) => {
|
|
7740
|
+
const statusBg = summary.status === "complete" ? "bg-green-50/50 dark:bg-green-950/30" : summary.status === "critical" ? "bg-red-50/50 dark:bg-red-950/30" : summary.status === "warning" ? "bg-amber-50/50 dark:bg-amber-950/30" : "bg-muted/30";
|
|
7741
|
+
const statusText = summary.status === "complete" ? "text-green-700 dark:text-green-300" : summary.status === "critical" ? "text-red-700 dark:text-red-300" : summary.status === "warning" ? "text-amber-700 dark:text-amber-300" : "text-muted-foreground";
|
|
7263
7742
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7264
7743
|
"th",
|
|
7265
7744
|
{
|
|
7266
7745
|
className: cn(
|
|
7267
|
-
"h-
|
|
7268
|
-
"border-r border-b border-border last:border-r-0
|
|
7269
|
-
|
|
7270
|
-
index === 0 && stickySupplierColumn && [
|
|
7271
|
-
"sticky left-0 z-30 min-w-[200px]",
|
|
7272
|
-
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7273
|
-
],
|
|
7274
|
-
index > 0 && "min-w-[140px]",
|
|
7275
|
-
// Current week: only highlight text/dot, not full background
|
|
7276
|
-
isCurrentWeekColumn && highlightCurrentWeek && "text-primary"
|
|
7746
|
+
"h-auto px-2 py-1.5 text-left align-middle",
|
|
7747
|
+
"border-r border-b border-border last:border-r-0 min-w-[140px]",
|
|
7748
|
+
statusBg
|
|
7277
7749
|
),
|
|
7278
|
-
children:
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7750
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
7751
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
7752
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: cn("h-3 w-3", statusText) }),
|
|
7753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-xs font-medium tabular-nums", statusText), children: [
|
|
7754
|
+
summary.producedTons.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
7755
|
+
" t"
|
|
7756
|
+
] })
|
|
7757
|
+
] }),
|
|
7758
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
7759
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3 w-3 text-muted-foreground" }),
|
|
7760
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground tabular-nums", children: [
|
|
7761
|
+
summary.sentDeliveries,
|
|
7762
|
+
"/",
|
|
7763
|
+
summary.plannedDeliveries,
|
|
7764
|
+
" sent"
|
|
7765
|
+
] })
|
|
7766
|
+
] })
|
|
7767
|
+
] })
|
|
7282
7768
|
},
|
|
7283
|
-
|
|
7769
|
+
summary.weekKey
|
|
7284
7770
|
);
|
|
7285
7771
|
})
|
|
7286
|
-
}
|
|
7287
|
-
|
|
7288
|
-
)) }),
|
|
7772
|
+
] })
|
|
7773
|
+
] }),
|
|
7289
7774
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-background", children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7290
7775
|
"tr",
|
|
7291
7776
|
{
|
|
@@ -7340,10 +7825,12 @@ function PlanningTable({
|
|
|
7340
7825
|
}
|
|
7341
7826
|
);
|
|
7342
7827
|
}
|
|
7343
|
-
function getStatusBadgeVariant(status) {
|
|
7828
|
+
function getStatusBadgeVariant(status, isComplete) {
|
|
7829
|
+
if (isComplete) return "outline";
|
|
7344
7830
|
switch (status) {
|
|
7345
7831
|
case "on-time":
|
|
7346
7832
|
return "outline";
|
|
7833
|
+
// Grey for on-track
|
|
7347
7834
|
case "delayed":
|
|
7348
7835
|
return "secondary";
|
|
7349
7836
|
case "critical":
|
|
@@ -7352,19 +7839,24 @@ function getStatusBadgeVariant(status) {
|
|
|
7352
7839
|
return "outline";
|
|
7353
7840
|
}
|
|
7354
7841
|
}
|
|
7355
|
-
function getStatusBadgeClasses(status) {
|
|
7842
|
+
function getStatusBadgeClasses(status, isComplete) {
|
|
7843
|
+
if (isComplete) {
|
|
7844
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7845
|
+
}
|
|
7356
7846
|
switch (status) {
|
|
7357
7847
|
case "on-time":
|
|
7358
|
-
return "border-
|
|
7848
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
7849
|
+
// Grey for on-track
|
|
7359
7850
|
case "delayed":
|
|
7360
7851
|
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
7361
7852
|
case "critical":
|
|
7362
7853
|
return "";
|
|
7363
7854
|
default:
|
|
7364
|
-
return "";
|
|
7855
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
7365
7856
|
}
|
|
7366
7857
|
}
|
|
7367
|
-
function getStatusLabel(status) {
|
|
7858
|
+
function getStatusLabel(status, isComplete) {
|
|
7859
|
+
if (isComplete) return "Complete";
|
|
7368
7860
|
switch (status) {
|
|
7369
7861
|
case "on-time":
|
|
7370
7862
|
return "On Track";
|
|
@@ -7378,10 +7870,12 @@ function getStatusLabel(status) {
|
|
|
7378
7870
|
return status;
|
|
7379
7871
|
}
|
|
7380
7872
|
}
|
|
7381
|
-
function getProgressVariant(status) {
|
|
7873
|
+
function getProgressVariant(status, isComplete) {
|
|
7874
|
+
if (isComplete) return "success";
|
|
7382
7875
|
switch (status) {
|
|
7383
7876
|
case "on-time":
|
|
7384
|
-
return "
|
|
7877
|
+
return "default";
|
|
7878
|
+
// Grey/default for on-track
|
|
7385
7879
|
case "delayed":
|
|
7386
7880
|
return "warning";
|
|
7387
7881
|
case "critical":
|
|
@@ -7666,37 +8160,66 @@ function DeliveryListItem({
|
|
|
7666
8160
|
onClick
|
|
7667
8161
|
}) {
|
|
7668
8162
|
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
8163
|
+
const isComplete = (delivery.progress ?? 0) >= 100;
|
|
8164
|
+
const getCardStyles3 = () => {
|
|
8165
|
+
if (delivery.status === "critical") {
|
|
8166
|
+
return {
|
|
8167
|
+
card: "border-l-[3px] border-l-red-500 bg-red-50/50 dark:bg-red-950/30",
|
|
8168
|
+
icon: "text-red-600 dark:text-red-400",
|
|
8169
|
+
title: "text-foreground",
|
|
8170
|
+
subtitle: "text-red-700/70 dark:text-red-300/70",
|
|
8171
|
+
chevron: "text-red-600/60 dark:text-red-400/60"
|
|
8172
|
+
};
|
|
8173
|
+
}
|
|
8174
|
+
if (delivery.status === "delayed") {
|
|
8175
|
+
return {
|
|
8176
|
+
card: "border-l-[3px] border-l-amber-500 bg-amber-50/50 dark:bg-amber-950/30",
|
|
8177
|
+
icon: "text-amber-600 dark:text-amber-400",
|
|
8178
|
+
title: "text-foreground",
|
|
8179
|
+
subtitle: "text-amber-700/70 dark:text-amber-300/70",
|
|
8180
|
+
chevron: "text-amber-600/60 dark:text-amber-400/60"
|
|
8181
|
+
};
|
|
8182
|
+
}
|
|
8183
|
+
if (isComplete) {
|
|
8184
|
+
return {
|
|
8185
|
+
card: "border-l-[3px] border-l-green-500 bg-green-50/50 dark:bg-green-950/30",
|
|
8186
|
+
icon: "text-green-600 dark:text-green-400",
|
|
8187
|
+
title: "text-foreground",
|
|
8188
|
+
subtitle: "text-green-700/70 dark:text-green-300/70",
|
|
8189
|
+
chevron: "text-green-600/60 dark:text-green-400/60"
|
|
8190
|
+
};
|
|
8191
|
+
}
|
|
8192
|
+
return {
|
|
8193
|
+
card: "border-l-[3px] border-l-muted-foreground/40 bg-muted/30 dark:bg-muted/20",
|
|
8194
|
+
icon: "text-muted-foreground",
|
|
8195
|
+
title: "text-foreground",
|
|
8196
|
+
subtitle: "text-muted-foreground",
|
|
8197
|
+
chevron: "text-muted-foreground/60"
|
|
8198
|
+
};
|
|
8199
|
+
};
|
|
8200
|
+
const styles = getCardStyles3();
|
|
7669
8201
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7670
8202
|
"button",
|
|
7671
8203
|
{
|
|
7672
8204
|
onClick,
|
|
7673
8205
|
className: cn(
|
|
7674
8206
|
"w-full flex items-center justify-between p-3 rounded-lg",
|
|
7675
|
-
"
|
|
7676
|
-
"
|
|
8207
|
+
"transition-all duration-200 ease-out cursor-pointer text-left",
|
|
8208
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8209
|
+
styles.card
|
|
7677
8210
|
),
|
|
7678
8211
|
children: [
|
|
7679
8212
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7680
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7681
|
-
"flex items-center justify-center h-8 w-8 rounded-lg",
|
|
7682
|
-
delivery.status === "on-time" && "bg-green-100 dark:bg-green-950/50",
|
|
7683
|
-
delivery.status === "delayed" && "bg-amber-100 dark:bg-amber-950/50",
|
|
7684
|
-
delivery.status === "critical" && "bg-red-100 dark:bg-red-950/50"
|
|
7685
|
-
), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn(
|
|
7686
|
-
"h-4 w-4",
|
|
7687
|
-
delivery.status === "on-time" && "text-green-600 dark:text-green-400",
|
|
7688
|
-
delivery.status === "delayed" && "text-amber-600 dark:text-amber-400",
|
|
7689
|
-
delivery.status === "critical" && "text-red-600 dark:text-red-400"
|
|
7690
|
-
) }) }),
|
|
8213
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-5 w-5 shrink-0", styles.icon) }),
|
|
7691
8214
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7692
8215
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7693
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: delivery.label || `Delivery ${index + 1}` }),
|
|
8216
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm font-medium", styles.title), children: delivery.label || `Delivery ${index + 1}` }),
|
|
7694
8217
|
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
7695
8218
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3 w-3 text-muted-foreground" }),
|
|
7696
8219
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-primary" })
|
|
7697
8220
|
] })
|
|
7698
8221
|
] }),
|
|
7699
|
-
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs
|
|
8222
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-xs", styles.subtitle), children: [
|
|
7700
8223
|
"\u2192 ",
|
|
7701
8224
|
delivery.destination
|
|
7702
8225
|
] })
|
|
@@ -7706,12 +8229,12 @@ function DeliveryListItem({
|
|
|
7706
8229
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
8230
|
Badge,
|
|
7708
8231
|
{
|
|
7709
|
-
variant: getStatusBadgeVariant(delivery.status),
|
|
7710
|
-
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7711
|
-
children: getStatusLabel(delivery.status)
|
|
8232
|
+
variant: getStatusBadgeVariant(delivery.status, isComplete),
|
|
8233
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status, isComplete)),
|
|
8234
|
+
children: getStatusLabel(delivery.status, isComplete)
|
|
7712
8235
|
}
|
|
7713
8236
|
),
|
|
7714
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4
|
|
8237
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: cn("h-4 w-4", styles.chevron) })
|
|
7715
8238
|
] })
|
|
7716
8239
|
]
|
|
7717
8240
|
}
|
|
@@ -7782,9 +8305,9 @@ function DeliveryDetailsView({
|
|
|
7782
8305
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7783
8306
|
Badge,
|
|
7784
8307
|
{
|
|
7785
|
-
variant: getStatusBadgeVariant(delivery.status),
|
|
7786
|
-
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7787
|
-
children: getStatusLabel(delivery.status)
|
|
8308
|
+
variant: getStatusBadgeVariant(delivery.status, sentCount === totalCount && totalCount > 0),
|
|
8309
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status, sentCount === totalCount && totalCount > 0)),
|
|
8310
|
+
children: getStatusLabel(delivery.status, sentCount === totalCount && totalCount > 0)
|
|
7788
8311
|
}
|
|
7789
8312
|
)
|
|
7790
8313
|
] })
|
|
@@ -7957,9 +8480,9 @@ function MainView({
|
|
|
7957
8480
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7958
8481
|
Badge,
|
|
7959
8482
|
{
|
|
7960
|
-
variant: getStatusBadgeVariant(productionStatus),
|
|
7961
|
-
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus)),
|
|
7962
|
-
children: getStatusLabel(productionStatus)
|
|
8483
|
+
variant: getStatusBadgeVariant(productionStatus, isComplete),
|
|
8484
|
+
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus, isComplete)),
|
|
8485
|
+
children: getStatusLabel(productionStatus, isComplete)
|
|
7963
8486
|
}
|
|
7964
8487
|
)
|
|
7965
8488
|
] }),
|
|
@@ -7970,7 +8493,7 @@ function MainView({
|
|
|
7970
8493
|
value: productionProgress,
|
|
7971
8494
|
size: 100,
|
|
7972
8495
|
strokeWidth: 10,
|
|
7973
|
-
variant: getProgressVariant(productionStatus),
|
|
8496
|
+
variant: getProgressVariant(productionStatus, isComplete),
|
|
7974
8497
|
showCheckmark: isComplete,
|
|
7975
8498
|
children: isComplete ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7976
8499
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-6 w-6 text-green-600" }),
|
|
@@ -8151,46 +8674,1083 @@ function WeekDetailDialog({
|
|
|
8151
8674
|
}
|
|
8152
8675
|
) }) });
|
|
8153
8676
|
}
|
|
8154
|
-
function
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
"
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8677
|
+
function getStatusBadgeVariant2(status, isComplete) {
|
|
8678
|
+
if (isComplete) return "outline";
|
|
8679
|
+
switch (status) {
|
|
8680
|
+
case "on-time":
|
|
8681
|
+
return "outline";
|
|
8682
|
+
// Grey for on-track
|
|
8683
|
+
case "delayed":
|
|
8684
|
+
return "secondary";
|
|
8685
|
+
case "critical":
|
|
8686
|
+
return "destructive";
|
|
8687
|
+
default:
|
|
8688
|
+
return "outline";
|
|
8689
|
+
}
|
|
8690
|
+
}
|
|
8691
|
+
function getStatusBadgeClasses2(status, isComplete) {
|
|
8692
|
+
if (isComplete) {
|
|
8693
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
8694
|
+
}
|
|
8695
|
+
switch (status) {
|
|
8696
|
+
case "on-time":
|
|
8697
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
8698
|
+
// Grey for on-track
|
|
8699
|
+
case "delayed":
|
|
8700
|
+
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
8701
|
+
case "critical":
|
|
8702
|
+
return "";
|
|
8703
|
+
default:
|
|
8704
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
function getStatusLabel2(status, isComplete) {
|
|
8708
|
+
if (isComplete) return "Complete";
|
|
8709
|
+
switch (status) {
|
|
8710
|
+
case "on-time":
|
|
8711
|
+
return "On Track";
|
|
8712
|
+
case "delayed":
|
|
8713
|
+
return "At Risk";
|
|
8714
|
+
case "critical":
|
|
8715
|
+
return "Critical";
|
|
8716
|
+
case "pending":
|
|
8717
|
+
return "Pending";
|
|
8718
|
+
default:
|
|
8719
|
+
return status;
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8722
|
+
function getShipmentStatusBadgeClasses2(status) {
|
|
8723
|
+
switch (status) {
|
|
8724
|
+
case "sent":
|
|
8725
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
8726
|
+
case "not-sent":
|
|
8727
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
8728
|
+
case "moved":
|
|
8729
|
+
return "border-blue-500 text-blue-600 bg-blue-50 dark:bg-blue-950/50";
|
|
8730
|
+
case "addon":
|
|
8731
|
+
return "border-purple-500 text-purple-600 bg-purple-50 dark:bg-purple-950/50";
|
|
8732
|
+
case "planned":
|
|
8733
|
+
default:
|
|
8734
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
8735
|
+
}
|
|
8736
|
+
}
|
|
8737
|
+
function getShipmentStatusRowBg2(status) {
|
|
8738
|
+
switch (status) {
|
|
8739
|
+
case "sent":
|
|
8740
|
+
return "bg-green-50/30 dark:bg-green-950/10";
|
|
8741
|
+
case "not-sent":
|
|
8742
|
+
return "bg-muted/30";
|
|
8743
|
+
case "moved":
|
|
8744
|
+
return "bg-blue-50/30 dark:bg-blue-950/10";
|
|
8745
|
+
case "addon":
|
|
8746
|
+
return "bg-purple-50/30 dark:bg-purple-950/10";
|
|
8747
|
+
default:
|
|
8748
|
+
return "";
|
|
8749
|
+
}
|
|
8750
|
+
}
|
|
8751
|
+
function ElementProductionDialog({
|
|
8752
|
+
open,
|
|
8753
|
+
onOpenChange,
|
|
8754
|
+
elements,
|
|
8755
|
+
onSave
|
|
8756
|
+
}) {
|
|
8757
|
+
const [searchQuery, setSearchQuery] = React27__namespace.useState("");
|
|
8758
|
+
const [selectedIds, setSelectedIds] = React27__namespace.useState(
|
|
8759
|
+
new Set(elements.filter((e) => e.isProduced).map((e) => e.id))
|
|
8760
|
+
);
|
|
8761
|
+
React27__namespace.useEffect(() => {
|
|
8762
|
+
if (open) {
|
|
8763
|
+
setSelectedIds(new Set(elements.filter((e) => e.isProduced).map((e) => e.id)));
|
|
8764
|
+
setSearchQuery("");
|
|
8765
|
+
}
|
|
8766
|
+
}, [open, elements]);
|
|
8767
|
+
const filteredElements = React27__namespace.useMemo(() => {
|
|
8768
|
+
if (!searchQuery.trim()) return elements;
|
|
8769
|
+
const query = searchQuery.toLowerCase();
|
|
8770
|
+
return elements.filter(
|
|
8771
|
+
(e) => e.name.toLowerCase().includes(query) || e.prefix?.toLowerCase().includes(query) || e.type?.toLowerCase().includes(query)
|
|
8772
|
+
);
|
|
8773
|
+
}, [elements, searchQuery]);
|
|
8774
|
+
React27__namespace.useMemo(() => {
|
|
8775
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
8776
|
+
elements.forEach((e) => {
|
|
8777
|
+
if (e.prefix) prefixes.add(e.prefix);
|
|
8778
|
+
});
|
|
8779
|
+
return Array.from(prefixes).sort();
|
|
8780
|
+
}, [elements]);
|
|
8781
|
+
const toggleElement = (id) => {
|
|
8782
|
+
setSelectedIds((prev) => {
|
|
8783
|
+
const next = new Set(prev);
|
|
8784
|
+
if (next.has(id)) {
|
|
8785
|
+
next.delete(id);
|
|
8786
|
+
} else {
|
|
8787
|
+
next.add(id);
|
|
8788
|
+
}
|
|
8789
|
+
return next;
|
|
8790
|
+
});
|
|
8791
|
+
};
|
|
8792
|
+
const selectAll = () => {
|
|
8793
|
+
setSelectedIds(new Set(filteredElements.map((e) => e.id)));
|
|
8794
|
+
};
|
|
8795
|
+
const deselectAll = () => {
|
|
8796
|
+
setSelectedIds(/* @__PURE__ */ new Set());
|
|
8797
|
+
};
|
|
8798
|
+
const handleSave = () => {
|
|
8799
|
+
onSave(Array.from(selectedIds));
|
|
8800
|
+
onOpenChange(false);
|
|
8801
|
+
};
|
|
8802
|
+
const selectedCount = selectedIds.size;
|
|
8803
|
+
const totalCount = elements.length;
|
|
8804
|
+
const selectedWeight = elements.filter((e) => selectedIds.has(e.id)).reduce((sum, e) => sum + (e.weight ?? 0), 0);
|
|
8805
|
+
const totalWeight = elements.reduce((sum, e) => sum + (e.weight ?? 0), 0);
|
|
8806
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-fit max-w-[950px] w-fit max-h-[85vh] flex flex-col gap-0 p-0 overflow-hidden", children: [
|
|
8807
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "w-full p-6 pb-0 shrink-0", children: [
|
|
8808
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Enter production progress" }),
|
|
8809
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
8810
|
+
"Mark elements as produced (",
|
|
8811
|
+
selectedCount,
|
|
8812
|
+
" / ",
|
|
8813
|
+
totalCount,
|
|
8814
|
+
" selected)"
|
|
8815
|
+
] })
|
|
8816
|
+
] }),
|
|
8817
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col p-6 pt-4 gap-4 overflow-hidden w-fit", children: [
|
|
8818
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-3 shrink-0", children: [
|
|
8819
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
|
|
8820
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
8821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8822
|
+
Input,
|
|
8823
|
+
{
|
|
8824
|
+
placeholder: "Search elements...",
|
|
8825
|
+
value: searchQuery,
|
|
8826
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
8827
|
+
className: "pl-9 w-full"
|
|
8828
|
+
}
|
|
8829
|
+
)
|
|
8830
|
+
] }),
|
|
8831
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
8832
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8833
|
+
Button,
|
|
8834
|
+
{
|
|
8835
|
+
variant: "outline",
|
|
8836
|
+
size: "sm",
|
|
8837
|
+
onClick: selectAll,
|
|
8838
|
+
children: "Select all"
|
|
8839
|
+
}
|
|
8840
|
+
),
|
|
8841
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8842
|
+
Button,
|
|
8843
|
+
{
|
|
8844
|
+
variant: "outline",
|
|
8845
|
+
size: "sm",
|
|
8846
|
+
onClick: deselectAll,
|
|
8847
|
+
children: "Deselect all"
|
|
8848
|
+
}
|
|
8849
|
+
)
|
|
8850
|
+
] })
|
|
8851
|
+
] }),
|
|
8852
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 rounded-lg border bg-card overflow-hidden", children: filteredElements.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-full w-fit", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
8853
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { className: "sticky top-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "bg-muted/50 hover:bg-muted/50", children: [
|
|
8854
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-[44px] bg-muted/50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8855
|
+
Checkbox,
|
|
8856
|
+
{
|
|
8857
|
+
checked: selectedIds.size === filteredElements.length && filteredElements.length > 0,
|
|
8858
|
+
onCheckedChange: (checked) => {
|
|
8859
|
+
if (checked) {
|
|
8860
|
+
selectAll();
|
|
8861
|
+
} else {
|
|
8862
|
+
deselectAll();
|
|
8863
|
+
}
|
|
8864
|
+
},
|
|
8865
|
+
"aria-label": "Select all elements"
|
|
8866
|
+
}
|
|
8867
|
+
) }),
|
|
8868
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50", children: "Element" }),
|
|
8869
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 w-[80px]", children: "Type" }),
|
|
8870
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-right w-[90px]", children: "Weight" }),
|
|
8871
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-right w-[80px]", children: "Size" }),
|
|
8872
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-center w-[100px]", children: "Status" })
|
|
8873
|
+
] }) }),
|
|
8874
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: filteredElements.map((element) => {
|
|
8875
|
+
const isSelected = selectedIds.has(element.id);
|
|
8876
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8877
|
+
TableRow,
|
|
8878
|
+
{
|
|
8879
|
+
className: cn(
|
|
8880
|
+
"cursor-pointer transition-colors",
|
|
8881
|
+
isSelected && "bg-green-50/50 dark:bg-green-950/20"
|
|
8882
|
+
),
|
|
8883
|
+
onClick: () => toggleElement(element.id),
|
|
8884
|
+
children: [
|
|
8885
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "w-[44px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8886
|
+
Checkbox,
|
|
8887
|
+
{
|
|
8888
|
+
checked: isSelected,
|
|
8889
|
+
onCheckedChange: () => toggleElement(element.id),
|
|
8890
|
+
onClick: (e) => e.stopPropagation(),
|
|
8891
|
+
"aria-label": `Mark ${element.name} as produced`
|
|
8892
|
+
}
|
|
8893
|
+
) }),
|
|
8894
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8895
|
+
element.prefix && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "text-[10px] h-5 shrink-0 font-mono", children: element.prefix }),
|
|
8896
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: element.name })
|
|
8897
|
+
] }) }),
|
|
8898
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-muted-foreground w-[80px]", children: element.type || "\u2014" }),
|
|
8899
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums text-muted-foreground w-[90px]", children: element.weight != null ? `${element.weight.toLocaleString()} kg` : "\u2014" }),
|
|
8900
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums text-muted-foreground w-[80px]", children: element.size != null ? `${element.size.toLocaleString()} ${element.sizeUnit || "sqm"}` : "\u2014" }),
|
|
8901
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-center w-[100px]", children: isSelected ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8902
|
+
Badge,
|
|
8903
|
+
{
|
|
8904
|
+
variant: "outline",
|
|
8905
|
+
className: "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50",
|
|
8906
|
+
children: [
|
|
8907
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3 mr-1" }),
|
|
8908
|
+
"Produced"
|
|
8909
|
+
]
|
|
8910
|
+
}
|
|
8911
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8912
|
+
Badge,
|
|
8913
|
+
{
|
|
8914
|
+
variant: "outline",
|
|
8915
|
+
className: "border-muted-foreground/50 text-muted-foreground",
|
|
8916
|
+
children: "Not produced"
|
|
8917
|
+
}
|
|
8918
|
+
) })
|
|
8919
|
+
]
|
|
8920
|
+
},
|
|
8921
|
+
element.id
|
|
8922
|
+
);
|
|
8923
|
+
}) })
|
|
8924
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full min-h-[200px] text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
8925
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-10 w-10 mx-auto mb-3 opacity-50" }),
|
|
8926
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "No elements found" }),
|
|
8927
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Try adjusting your search" })
|
|
8928
|
+
] }) }) })
|
|
8929
|
+
] }),
|
|
8930
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { className: "w-full p-6 pt-4 border-t shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between w-full gap-4", children: [
|
|
8931
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
8932
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
8933
|
+
selectedCount,
|
|
8934
|
+
" / ",
|
|
8935
|
+
totalCount,
|
|
8936
|
+
" elements"
|
|
8937
|
+
] }),
|
|
8938
|
+
totalWeight > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8939
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2022" }),
|
|
8940
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums font-medium text-foreground", children: [
|
|
8941
|
+
(selectedWeight / 1e3).toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
8942
|
+
" / ",
|
|
8943
|
+
(totalWeight / 1e3).toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
8944
|
+
" ton"
|
|
8945
|
+
] })
|
|
8946
|
+
] })
|
|
8947
|
+
] }),
|
|
8948
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
8949
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
8950
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleSave, children: "Save progress" })
|
|
8951
|
+
] })
|
|
8952
|
+
] }) })
|
|
8953
|
+
] }) });
|
|
8954
|
+
}
|
|
8955
|
+
function DeliveryCommentPopover2({
|
|
8956
|
+
comments = [],
|
|
8957
|
+
onAddComment,
|
|
8958
|
+
deliveryLabel
|
|
8959
|
+
}) {
|
|
8960
|
+
const [open, setOpen] = React27__namespace.useState(false);
|
|
8961
|
+
const [newCommentText, setNewCommentText] = React27__namespace.useState("");
|
|
8962
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React27__namespace.useState(true);
|
|
8963
|
+
const [showAddForm, setShowAddForm] = React27__namespace.useState(false);
|
|
8964
|
+
const handleSubmit = () => {
|
|
8965
|
+
if (newCommentText.trim() && onAddComment) {
|
|
8966
|
+
onAddComment(newCommentText.trim());
|
|
8967
|
+
setNewCommentText("");
|
|
8968
|
+
setShowAddForm(false);
|
|
8969
|
+
setViewCommentsOpen(true);
|
|
8970
|
+
}
|
|
8971
|
+
};
|
|
8972
|
+
const handleKeyDown = (e) => {
|
|
8973
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
8974
|
+
e.preventDefault();
|
|
8975
|
+
handleSubmit();
|
|
8976
|
+
}
|
|
8977
|
+
if (e.key === "Escape") {
|
|
8978
|
+
setShowAddForm(false);
|
|
8979
|
+
setNewCommentText("");
|
|
8980
|
+
}
|
|
8981
|
+
};
|
|
8982
|
+
const formatDate3 = (date) => {
|
|
8983
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
8984
|
+
month: "short",
|
|
8985
|
+
day: "numeric",
|
|
8986
|
+
hour: "numeric",
|
|
8987
|
+
minute: "2-digit"
|
|
8988
|
+
}).format(date);
|
|
8989
|
+
};
|
|
8990
|
+
React27__namespace.useEffect(() => {
|
|
8991
|
+
if (!open) {
|
|
8992
|
+
setShowAddForm(false);
|
|
8993
|
+
setNewCommentText("");
|
|
8994
|
+
}
|
|
8995
|
+
}, [open]);
|
|
8996
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
8997
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
8998
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8999
|
+
PopoverContent,
|
|
9000
|
+
{
|
|
9001
|
+
className: "w-80 p-0 z-[100]",
|
|
9002
|
+
align: "end",
|
|
9003
|
+
sideOffset: 8,
|
|
9004
|
+
collisionPadding: 16,
|
|
9005
|
+
children: [
|
|
9006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
9007
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
9008
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: deliveryLabel })
|
|
9009
|
+
] }),
|
|
9010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 space-y-2 h-fit overflow-y-auto", children: [
|
|
9011
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
9012
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", className: "w-full justify-between h-8 px-2", children: [
|
|
9013
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium", children: [
|
|
9014
|
+
"Comments ",
|
|
9015
|
+
comments.length > 0 && `(${comments.length})`
|
|
9016
|
+
] }),
|
|
9017
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
|
|
9018
|
+
"h-4 w-4 transition-transform duration-200",
|
|
9019
|
+
viewCommentsOpen && "rotate-180"
|
|
9020
|
+
) })
|
|
9021
|
+
] }) }),
|
|
9022
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-3 space-y-2", children: [
|
|
9023
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9024
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
9025
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
9026
|
+
] }),
|
|
9027
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
9028
|
+
] }, comment.id)) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
9029
|
+
] }),
|
|
9030
|
+
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
9031
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9032
|
+
Button,
|
|
9033
|
+
{
|
|
9034
|
+
variant: "outline",
|
|
9035
|
+
size: "sm",
|
|
9036
|
+
className: "w-full justify-center gap-2 h-8",
|
|
9037
|
+
onClick: () => setShowAddForm(true),
|
|
9038
|
+
children: [
|
|
9039
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
9040
|
+
"Add comment"
|
|
9041
|
+
]
|
|
9042
|
+
}
|
|
9043
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
9044
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
9045
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
9046
|
+
), children: [
|
|
9047
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9048
|
+
Textarea,
|
|
9049
|
+
{
|
|
9050
|
+
placeholder: "Type your comment...",
|
|
9051
|
+
value: newCommentText,
|
|
9052
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
9053
|
+
onKeyDown: handleKeyDown,
|
|
9054
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
9055
|
+
autoFocus: true
|
|
9056
|
+
}
|
|
9057
|
+
),
|
|
9058
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9059
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
9060
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9061
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9062
|
+
Button,
|
|
9063
|
+
{
|
|
9064
|
+
variant: "ghost",
|
|
9065
|
+
size: "sm",
|
|
9066
|
+
className: "h-7",
|
|
9067
|
+
onClick: () => {
|
|
9068
|
+
setShowAddForm(false);
|
|
9069
|
+
setNewCommentText("");
|
|
9070
|
+
},
|
|
9071
|
+
children: "Cancel"
|
|
9072
|
+
}
|
|
9073
|
+
),
|
|
9074
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9075
|
+
Button,
|
|
9076
|
+
{
|
|
9077
|
+
size: "sm",
|
|
9078
|
+
className: "h-7 gap-1",
|
|
9079
|
+
onClick: handleSubmit,
|
|
9080
|
+
disabled: !newCommentText.trim(),
|
|
9081
|
+
children: [
|
|
9082
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
9083
|
+
"Save"
|
|
9084
|
+
]
|
|
9085
|
+
}
|
|
9086
|
+
)
|
|
9087
|
+
] })
|
|
9088
|
+
] })
|
|
9089
|
+
] })
|
|
9090
|
+
] })
|
|
9091
|
+
]
|
|
9092
|
+
}
|
|
9093
|
+
)
|
|
9094
|
+
] });
|
|
9095
|
+
}
|
|
9096
|
+
function ProductionCommentSection2({
|
|
9097
|
+
comments = [],
|
|
9098
|
+
onAddComment
|
|
9099
|
+
}) {
|
|
9100
|
+
const [showAddForm, setShowAddForm] = React27__namespace.useState(false);
|
|
9101
|
+
const [newComment, setNewComment] = React27__namespace.useState("");
|
|
9102
|
+
const handleSubmit = () => {
|
|
9103
|
+
if (newComment.trim() && onAddComment) {
|
|
9104
|
+
onAddComment(newComment.trim());
|
|
9105
|
+
setNewComment("");
|
|
9106
|
+
setShowAddForm(false);
|
|
9107
|
+
}
|
|
9108
|
+
};
|
|
9109
|
+
const handleKeyDown = (e) => {
|
|
9110
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
9111
|
+
e.preventDefault();
|
|
9112
|
+
handleSubmit();
|
|
9113
|
+
}
|
|
9114
|
+
if (e.key === "Escape") {
|
|
9115
|
+
setShowAddForm(false);
|
|
9116
|
+
setNewComment("");
|
|
9117
|
+
}
|
|
9118
|
+
};
|
|
9119
|
+
const formatDate3 = (date) => {
|
|
9120
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
9121
|
+
month: "short",
|
|
9122
|
+
day: "numeric",
|
|
9123
|
+
hour: "numeric",
|
|
9124
|
+
minute: "2-digit"
|
|
9125
|
+
}).format(date);
|
|
9126
|
+
};
|
|
9127
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9128
|
+
comments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-2.5 space-y-1", children: [
|
|
9129
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9130
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
9131
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
9132
|
+
] }),
|
|
9133
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
9134
|
+
] }, comment.id)) }),
|
|
9135
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9136
|
+
Button,
|
|
9137
|
+
{
|
|
9138
|
+
variant: "ghost",
|
|
9139
|
+
size: "sm",
|
|
9140
|
+
className: "w-full justify-start gap-2 h-8 text-muted-foreground",
|
|
9141
|
+
onClick: () => setShowAddForm(true),
|
|
9142
|
+
children: [
|
|
9143
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5" }),
|
|
9144
|
+
comments.length > 0 ? "Add another comment" : "Add a comment..."
|
|
9145
|
+
]
|
|
9146
|
+
}
|
|
9147
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 animate-in fade-in-0 slide-in-from-top-2 duration-200", children: [
|
|
9148
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9149
|
+
Textarea,
|
|
9150
|
+
{
|
|
9151
|
+
placeholder: "Add a comment...",
|
|
9152
|
+
value: newComment,
|
|
9153
|
+
onChange: (e) => setNewComment(e.target.value),
|
|
9154
|
+
onKeyDown: handleKeyDown,
|
|
9155
|
+
className: "min-h-[60px] text-sm resize-none",
|
|
9156
|
+
autoFocus: true
|
|
9157
|
+
}
|
|
9158
|
+
),
|
|
9159
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9160
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send" }),
|
|
9161
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9162
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9163
|
+
Button,
|
|
9164
|
+
{
|
|
9165
|
+
variant: "ghost",
|
|
9166
|
+
size: "sm",
|
|
9167
|
+
className: "h-7",
|
|
9168
|
+
onClick: () => {
|
|
9169
|
+
setShowAddForm(false);
|
|
9170
|
+
setNewComment("");
|
|
9171
|
+
},
|
|
9172
|
+
children: "Cancel"
|
|
9173
|
+
}
|
|
9174
|
+
),
|
|
9175
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9176
|
+
Button,
|
|
9177
|
+
{
|
|
9178
|
+
size: "sm",
|
|
9179
|
+
className: "h-7 gap-1",
|
|
9180
|
+
onClick: handleSubmit,
|
|
9181
|
+
disabled: !newComment.trim(),
|
|
9182
|
+
children: [
|
|
9183
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
9184
|
+
"Save"
|
|
9185
|
+
]
|
|
9186
|
+
}
|
|
9187
|
+
)
|
|
9188
|
+
] })
|
|
9189
|
+
] })
|
|
9190
|
+
] })
|
|
9191
|
+
] });
|
|
9192
|
+
}
|
|
9193
|
+
function DeliveryListItem2({
|
|
9194
|
+
delivery,
|
|
9195
|
+
index,
|
|
9196
|
+
onClick
|
|
9197
|
+
}) {
|
|
9198
|
+
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
9199
|
+
const isComplete = (delivery.progress ?? 0) >= 100;
|
|
9200
|
+
const getCardStyles3 = () => {
|
|
9201
|
+
if (delivery.status === "critical") {
|
|
9202
|
+
return {
|
|
9203
|
+
card: "border-l-[3px] border-l-red-500 bg-red-50/50 dark:bg-red-950/30",
|
|
9204
|
+
icon: "text-red-600 dark:text-red-400",
|
|
9205
|
+
title: "text-foreground",
|
|
9206
|
+
subtitle: "text-red-700/70 dark:text-red-300/70",
|
|
9207
|
+
chevron: "text-red-600/60 dark:text-red-400/60"
|
|
9208
|
+
};
|
|
9209
|
+
}
|
|
9210
|
+
if (delivery.status === "delayed") {
|
|
9211
|
+
return {
|
|
9212
|
+
card: "border-l-[3px] border-l-amber-500 bg-amber-50/50 dark:bg-amber-950/30",
|
|
9213
|
+
icon: "text-amber-600 dark:text-amber-400",
|
|
9214
|
+
title: "text-foreground",
|
|
9215
|
+
subtitle: "text-amber-700/70 dark:text-amber-300/70",
|
|
9216
|
+
chevron: "text-amber-600/60 dark:text-amber-400/60"
|
|
9217
|
+
};
|
|
9218
|
+
}
|
|
9219
|
+
if (isComplete) {
|
|
9220
|
+
return {
|
|
9221
|
+
card: "border-l-[3px] border-l-green-500 bg-green-50/50 dark:bg-green-950/30",
|
|
9222
|
+
icon: "text-green-600 dark:text-green-400",
|
|
9223
|
+
title: "text-foreground",
|
|
9224
|
+
subtitle: "text-green-700/70 dark:text-green-300/70",
|
|
9225
|
+
chevron: "text-green-600/60 dark:text-green-400/60"
|
|
9226
|
+
};
|
|
9227
|
+
}
|
|
9228
|
+
return {
|
|
9229
|
+
card: "border-l-[3px] border-l-muted-foreground/40 bg-muted/30 dark:bg-muted/20",
|
|
9230
|
+
icon: "text-muted-foreground",
|
|
9231
|
+
title: "text-foreground",
|
|
9232
|
+
subtitle: "text-muted-foreground",
|
|
9233
|
+
chevron: "text-muted-foreground/60"
|
|
9234
|
+
};
|
|
9235
|
+
};
|
|
9236
|
+
const styles = getCardStyles3();
|
|
9237
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9238
|
+
"button",
|
|
9239
|
+
{
|
|
9240
|
+
onClick,
|
|
9241
|
+
className: cn(
|
|
9242
|
+
"w-full flex items-center justify-between p-3 rounded-lg",
|
|
9243
|
+
"transition-all duration-200 ease-out cursor-pointer text-left",
|
|
9244
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
9245
|
+
styles.card
|
|
9246
|
+
),
|
|
9247
|
+
children: [
|
|
9248
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9249
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-5 w-5 shrink-0", styles.icon) }),
|
|
9250
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
9251
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9252
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm font-medium", styles.title), children: delivery.label || `Delivery ${index + 1}` }),
|
|
9253
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
9254
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3 w-3 text-muted-foreground" }),
|
|
9255
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-primary" })
|
|
9256
|
+
] })
|
|
9257
|
+
] }),
|
|
9258
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-xs", styles.subtitle), children: [
|
|
9259
|
+
"\u2192 ",
|
|
9260
|
+
delivery.destination
|
|
9261
|
+
] })
|
|
9262
|
+
] })
|
|
9263
|
+
] }),
|
|
9264
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9265
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9266
|
+
Badge,
|
|
9267
|
+
{
|
|
9268
|
+
variant: getStatusBadgeVariant2(delivery.status, isComplete),
|
|
9269
|
+
className: cn("text-xs", getStatusBadgeClasses2(delivery.status, isComplete)),
|
|
9270
|
+
children: getStatusLabel2(delivery.status, isComplete)
|
|
9271
|
+
}
|
|
9272
|
+
),
|
|
9273
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: cn("h-4 w-4", styles.chevron) })
|
|
9274
|
+
] })
|
|
9275
|
+
]
|
|
9276
|
+
}
|
|
9277
|
+
);
|
|
9278
|
+
}
|
|
9279
|
+
function DeliveryDetailsView2({
|
|
9280
|
+
delivery,
|
|
9281
|
+
week,
|
|
9282
|
+
onBack,
|
|
9283
|
+
onAddComment
|
|
9284
|
+
}) {
|
|
9285
|
+
const elements = delivery.elements ?? [];
|
|
9286
|
+
const categorizedElements = React27__namespace.useMemo(() => {
|
|
9287
|
+
const sent = [];
|
|
9288
|
+
const notSent = [];
|
|
9289
|
+
const moved = [];
|
|
9290
|
+
const addons = [];
|
|
9291
|
+
elements.forEach((element) => {
|
|
9292
|
+
const status = getElementShipmentStatus(element, delivery.id);
|
|
9293
|
+
switch (status) {
|
|
9294
|
+
case "sent":
|
|
9295
|
+
sent.push(element);
|
|
9296
|
+
break;
|
|
9297
|
+
case "not-sent":
|
|
9298
|
+
notSent.push(element);
|
|
9299
|
+
break;
|
|
9300
|
+
case "moved":
|
|
9301
|
+
moved.push(element);
|
|
9302
|
+
break;
|
|
9303
|
+
case "addon":
|
|
9304
|
+
addons.push(element);
|
|
9305
|
+
break;
|
|
9306
|
+
default:
|
|
9307
|
+
notSent.push(element);
|
|
9308
|
+
}
|
|
9309
|
+
});
|
|
9310
|
+
return { sent, notSent, moved, addons };
|
|
9311
|
+
}, [elements, delivery.id]);
|
|
9312
|
+
const totalCount = elements.length;
|
|
9313
|
+
const sentCount = categorizedElements.sent.length;
|
|
9314
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full animate-in slide-in-from-right-4 duration-200", children: [
|
|
9315
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-4 py-3 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9316
|
+
Button,
|
|
9317
|
+
{
|
|
9318
|
+
variant: "ghost",
|
|
9319
|
+
size: "sm",
|
|
9320
|
+
className: "gap-1 -ml-2",
|
|
9321
|
+
onClick: onBack,
|
|
9322
|
+
children: [
|
|
9323
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }),
|
|
9324
|
+
"Back"
|
|
9325
|
+
]
|
|
9326
|
+
}
|
|
9327
|
+
) }),
|
|
9328
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-4 space-y-2", children: [
|
|
9329
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9330
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: delivery.label || "Delivery Details" }),
|
|
9331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9333
|
+
DeliveryCommentPopover2,
|
|
9334
|
+
{
|
|
9335
|
+
comments: delivery.comments,
|
|
9336
|
+
onAddComment,
|
|
9337
|
+
deliveryLabel: delivery.label || "Delivery"
|
|
9338
|
+
}
|
|
9339
|
+
),
|
|
9340
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9341
|
+
Badge,
|
|
9342
|
+
{
|
|
9343
|
+
variant: getStatusBadgeVariant2(delivery.status, sentCount === totalCount && totalCount > 0),
|
|
9344
|
+
className: cn("text-xs", getStatusBadgeClasses2(delivery.status, sentCount === totalCount && totalCount > 0)),
|
|
9345
|
+
children: getStatusLabel2(delivery.status, sentCount === totalCount && totalCount > 0)
|
|
9346
|
+
}
|
|
9347
|
+
)
|
|
9348
|
+
] })
|
|
9349
|
+
] }),
|
|
9350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
9351
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
9352
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-3.5 w-3.5" }),
|
|
9353
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9354
|
+
week.label,
|
|
9355
|
+
" \u2022 ",
|
|
9356
|
+
week.dateRange
|
|
9357
|
+
] })
|
|
9358
|
+
] }),
|
|
9359
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
9360
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3.5 w-3.5" }),
|
|
9361
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9362
|
+
"\u2192 ",
|
|
9363
|
+
delivery.destination
|
|
9364
|
+
] })
|
|
9365
|
+
] })
|
|
9366
|
+
] })
|
|
9367
|
+
] }),
|
|
9368
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-4 pb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
9369
|
+
totalCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-4 space-y-3", children: [
|
|
9370
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9371
|
+
StatusProgress,
|
|
9372
|
+
{
|
|
9373
|
+
value: totalCount > 0 ? sentCount / totalCount * 100 : 0,
|
|
9374
|
+
currentCount: sentCount,
|
|
9375
|
+
totalCount,
|
|
9376
|
+
unitLabel: "shipped",
|
|
9377
|
+
showLabel: true,
|
|
9378
|
+
showCheckmark: true,
|
|
9379
|
+
size: "md"
|
|
9380
|
+
}
|
|
9381
|
+
),
|
|
9382
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap", children: [
|
|
9383
|
+
categorizedElements.sent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9384
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-3 w-3 text-green-600" }),
|
|
9385
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-green-700 dark:text-green-300", children: [
|
|
9386
|
+
categorizedElements.sent.length,
|
|
9387
|
+
" Sent"
|
|
9388
|
+
] })
|
|
9389
|
+
] }),
|
|
9390
|
+
categorizedElements.notSent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9391
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-3 w-3 text-muted-foreground" }),
|
|
9392
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
9393
|
+
categorizedElements.notSent.length,
|
|
9394
|
+
" Missing"
|
|
9395
|
+
] })
|
|
9396
|
+
] }),
|
|
9397
|
+
categorizedElements.moved.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9398
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-3 w-3 text-blue-600" }),
|
|
9399
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-blue-700 dark:text-blue-300", children: [
|
|
9400
|
+
categorizedElements.moved.length,
|
|
9401
|
+
" Moved"
|
|
9402
|
+
] })
|
|
9403
|
+
] }),
|
|
9404
|
+
categorizedElements.addons.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9405
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3 text-purple-600" }),
|
|
9406
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-700 dark:text-purple-300", children: [
|
|
9407
|
+
categorizedElements.addons.length,
|
|
9408
|
+
" Add-on"
|
|
9409
|
+
] })
|
|
9410
|
+
] })
|
|
9411
|
+
] })
|
|
9412
|
+
] }),
|
|
9413
|
+
elements.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
9414
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Elements" }),
|
|
9415
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
9416
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "bg-sidebar hover:bg-sidebar", children: [
|
|
9417
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Prefix" }),
|
|
9418
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Type" }),
|
|
9419
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-right", children: "Weight" }),
|
|
9420
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-center", children: "Status" })
|
|
9421
|
+
] }) }),
|
|
9422
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: elements.map((element) => {
|
|
9423
|
+
const shipmentStatus = getElementShipmentStatus(element, delivery.id);
|
|
9424
|
+
const statusLabel = getShipmentStatusLabel(shipmentStatus);
|
|
9425
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9426
|
+
TableRow,
|
|
9427
|
+
{
|
|
9428
|
+
className: getShipmentStatusRowBg2(shipmentStatus),
|
|
9429
|
+
children: [
|
|
9430
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "font-medium", children: element.prefix || "\u2014" }),
|
|
9431
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: element.type || element.name || "\u2014" }),
|
|
9432
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums", children: element.weight ? `${element.weight} ${element.weightUnit || "kg"}` : "\u2014" }),
|
|
9433
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
9434
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9435
|
+
Badge,
|
|
9436
|
+
{
|
|
9437
|
+
variant: "outline",
|
|
9438
|
+
className: cn("text-[10px] h-5", getShipmentStatusBadgeClasses2(shipmentStatus)),
|
|
9439
|
+
children: statusLabel
|
|
9440
|
+
}
|
|
9441
|
+
),
|
|
9442
|
+
shipmentStatus === "moved" && element.actualDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-blue-600 dark:text-blue-400", children: [
|
|
9443
|
+
"\u2192 ",
|
|
9444
|
+
element.actualDeliveryLabel
|
|
9445
|
+
] }),
|
|
9446
|
+
shipmentStatus === "addon" && element.originalDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-purple-600 dark:text-purple-400", children: [
|
|
9447
|
+
"from ",
|
|
9448
|
+
element.originalDeliveryLabel
|
|
9449
|
+
] })
|
|
9450
|
+
] }) })
|
|
9451
|
+
]
|
|
9452
|
+
},
|
|
9453
|
+
element.id
|
|
9454
|
+
);
|
|
9455
|
+
}) })
|
|
9456
|
+
] }) })
|
|
9457
|
+
] }),
|
|
9458
|
+
elements.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
9459
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
9460
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No elements in this delivery" })
|
|
9461
|
+
] })
|
|
9462
|
+
] }) })
|
|
9463
|
+
] });
|
|
9464
|
+
}
|
|
9465
|
+
function MainView2({
|
|
9466
|
+
supplier,
|
|
9467
|
+
week,
|
|
9468
|
+
data,
|
|
9469
|
+
productionElements,
|
|
9470
|
+
previousProducedCount,
|
|
9471
|
+
onOpenProductionDialog,
|
|
9472
|
+
onSelectDelivery,
|
|
9473
|
+
onAddProductionComment
|
|
9474
|
+
}) {
|
|
9475
|
+
const production = data?.production;
|
|
9476
|
+
const producedCount = productionElements.filter((e) => e.isProduced).length;
|
|
9477
|
+
const totalCount = productionElements.length;
|
|
9478
|
+
const productionProgress = totalCount > 0 ? Math.round(producedCount / totalCount * 100) : 0;
|
|
9479
|
+
const isComplete = productionProgress >= 100;
|
|
9480
|
+
const hasProductionComments = (production?.comments?.length ?? 0) > 0;
|
|
9481
|
+
const showPreviousProgress = !isComplete && previousProducedCount !== void 0 && previousProducedCount !== producedCount;
|
|
9482
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-in fade-in-0 duration-200", children: [
|
|
9483
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetHeader, { className: "px-4 pt-4 pb-3 border-b", children: [
|
|
9484
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetTitle, { className: "flex items-center gap-2", children: [
|
|
9485
|
+
supplier.name,
|
|
9486
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs font-normal", children: supplier.badgeType })
|
|
9487
|
+
] }),
|
|
9488
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetDescription, { className: "flex items-center gap-2", children: [
|
|
9489
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-4 w-4" }),
|
|
9490
|
+
week.label,
|
|
9491
|
+
" \u2022 ",
|
|
9492
|
+
week.dateRange
|
|
9493
|
+
] })
|
|
9494
|
+
] }),
|
|
9495
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-4 pb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pt-4", children: [
|
|
9496
|
+
data.type !== "empty" && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
9497
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9498
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-4 w-4 text-muted-foreground" }),
|
|
9499
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Production" })
|
|
9500
|
+
] }),
|
|
9501
|
+
totalCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
9502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center py-4", children: [
|
|
9503
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9504
|
+
CircularProgress,
|
|
9505
|
+
{
|
|
9506
|
+
value: productionProgress,
|
|
9507
|
+
size: 88,
|
|
9508
|
+
strokeWidth: 8,
|
|
9509
|
+
variant: productionProgress >= 100 ? "success" : productionProgress >= 50 ? "success" : productionProgress > 0 ? "warning" : "destructive",
|
|
9510
|
+
showCheckmark: true,
|
|
9511
|
+
children: productionProgress < 100 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold tabular-nums", children: [
|
|
9512
|
+
Math.round(productionProgress),
|
|
9513
|
+
"%"
|
|
9514
|
+
] })
|
|
9515
|
+
}
|
|
9516
|
+
),
|
|
9517
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 text-center", children: [
|
|
9518
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold text-foreground", children: [
|
|
9519
|
+
producedCount,
|
|
9520
|
+
" / ",
|
|
9521
|
+
totalCount,
|
|
9522
|
+
" elements"
|
|
9523
|
+
] }),
|
|
9524
|
+
showPreviousProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
9525
|
+
"Previously: ",
|
|
9526
|
+
previousProducedCount,
|
|
9527
|
+
" / ",
|
|
9528
|
+
totalCount
|
|
9529
|
+
] })
|
|
9530
|
+
] })
|
|
9531
|
+
] }),
|
|
9532
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9533
|
+
Button,
|
|
9534
|
+
{
|
|
9535
|
+
className: "w-full",
|
|
9536
|
+
onClick: onOpenProductionDialog,
|
|
9537
|
+
children: "Enter production progress"
|
|
9538
|
+
}
|
|
9539
|
+
)
|
|
9540
|
+
] }) : (
|
|
9541
|
+
/* No elements - show placeholder with button still available */
|
|
9542
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
9543
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-6 text-muted-foreground bg-muted/30 rounded-lg", children: [
|
|
9544
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
9545
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No elements to track" })
|
|
9546
|
+
] }),
|
|
9547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9548
|
+
Button,
|
|
9549
|
+
{
|
|
9550
|
+
className: "w-full",
|
|
9551
|
+
variant: "outline",
|
|
9552
|
+
onClick: onOpenProductionDialog,
|
|
9553
|
+
children: "Enter production progress"
|
|
9554
|
+
}
|
|
9555
|
+
)
|
|
9556
|
+
] })
|
|
9557
|
+
),
|
|
9558
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9559
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9560
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Comments" }),
|
|
9561
|
+
hasProductionComments && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
9562
|
+
"(",
|
|
9563
|
+
production?.comments?.length,
|
|
9564
|
+
")"
|
|
9565
|
+
] })
|
|
9566
|
+
] }),
|
|
9567
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9568
|
+
ProductionCommentSection2,
|
|
9569
|
+
{
|
|
9570
|
+
comments: production?.comments,
|
|
9571
|
+
onAddComment: onAddProductionComment
|
|
9572
|
+
}
|
|
9573
|
+
)
|
|
9574
|
+
] })
|
|
9575
|
+
] }),
|
|
9576
|
+
data.deliveries && data.deliveries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
9577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9578
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4 text-muted-foreground" }),
|
|
9579
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Deliveries" }),
|
|
9580
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground ml-auto", children: [
|
|
9581
|
+
data.deliveries.length,
|
|
9582
|
+
" scheduled"
|
|
9583
|
+
] })
|
|
9584
|
+
] }),
|
|
9585
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: data.deliveries.map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9586
|
+
DeliveryListItem2,
|
|
9587
|
+
{
|
|
9588
|
+
delivery,
|
|
9589
|
+
index,
|
|
9590
|
+
onClick: () => onSelectDelivery(delivery)
|
|
9591
|
+
},
|
|
9592
|
+
delivery.id
|
|
9593
|
+
)) })
|
|
9594
|
+
] }),
|
|
9595
|
+
data.type === "no-logistics" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-muted-foreground p-3 bg-muted/50 rounded-lg", children: [
|
|
9596
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4" }),
|
|
9597
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "No logistics scheduled for this week" })
|
|
9598
|
+
] }),
|
|
9599
|
+
data.hasWarning && data.warningMessage && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 rounded-lg bg-amber-50 dark:bg-amber-950/50 p-3 text-amber-700 dark:text-amber-300", children: [
|
|
9600
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }),
|
|
9601
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm", children: data.warningMessage })
|
|
9602
|
+
] }),
|
|
9603
|
+
data.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
9604
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Notes" }),
|
|
9605
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: data.notes })
|
|
9606
|
+
] })
|
|
9607
|
+
] }) })
|
|
9608
|
+
] });
|
|
9609
|
+
}
|
|
9610
|
+
function WeekDetailSheet({
|
|
9611
|
+
open,
|
|
9612
|
+
onOpenChange,
|
|
9613
|
+
supplier,
|
|
9614
|
+
week,
|
|
9615
|
+
data,
|
|
9616
|
+
onProductionUpdate,
|
|
9617
|
+
onAddProductionComment,
|
|
9618
|
+
onAddDeliveryComment
|
|
9619
|
+
}) {
|
|
9620
|
+
const [selectedDelivery, setSelectedDelivery] = React27__namespace.useState(null);
|
|
9621
|
+
const [productionDialogOpen, setProductionDialogOpen] = React27__namespace.useState(false);
|
|
9622
|
+
const [previousProducedCount, setPreviousProducedCount] = React27__namespace.useState(void 0);
|
|
9623
|
+
const productionElements = React27__namespace.useMemo(() => {
|
|
9624
|
+
if (!data?.deliveries) return [];
|
|
9625
|
+
const elements = [];
|
|
9626
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
9627
|
+
data.deliveries.forEach((delivery) => {
|
|
9628
|
+
delivery.elements?.forEach((element) => {
|
|
9629
|
+
if (!seenIds.has(element.id)) {
|
|
9630
|
+
seenIds.add(element.id);
|
|
9631
|
+
elements.push({
|
|
9632
|
+
id: element.id,
|
|
9633
|
+
name: element.name,
|
|
9634
|
+
prefix: element.prefix,
|
|
9635
|
+
type: element.type,
|
|
9636
|
+
weight: element.weight,
|
|
9637
|
+
size: element.sizeSqm,
|
|
9638
|
+
sizeUnit: "sqm",
|
|
9639
|
+
isProduced: element.isProduced
|
|
9640
|
+
});
|
|
9641
|
+
}
|
|
9642
|
+
});
|
|
9643
|
+
});
|
|
9644
|
+
return elements;
|
|
9645
|
+
}, [data?.deliveries]);
|
|
9646
|
+
const currentProducedCount = productionElements.filter((e) => e.isProduced).length;
|
|
9647
|
+
React27__namespace.useEffect(() => {
|
|
9648
|
+
if (open && data?.deliveries) {
|
|
9649
|
+
setPreviousProducedCount(currentProducedCount);
|
|
9650
|
+
}
|
|
9651
|
+
}, [open]);
|
|
9652
|
+
React27__namespace.useEffect(() => {
|
|
9653
|
+
if (!open) {
|
|
9654
|
+
setSelectedDelivery(null);
|
|
9655
|
+
setProductionDialogOpen(false);
|
|
9656
|
+
setPreviousProducedCount(void 0);
|
|
9657
|
+
}
|
|
9658
|
+
}, [open]);
|
|
9659
|
+
const handleProductionSave = (producedIds) => {
|
|
9660
|
+
if (!supplier || !week || !onProductionUpdate) return;
|
|
9661
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9662
|
+
onProductionUpdate(supplier.id, weekKey, producedIds);
|
|
9663
|
+
setPreviousProducedCount(producedIds.length);
|
|
9664
|
+
};
|
|
9665
|
+
if (!supplier || !week || !data) {
|
|
9666
|
+
return null;
|
|
9667
|
+
}
|
|
9668
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9669
|
+
/* @__PURE__ */ jsxRuntime.jsx(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9670
|
+
SheetContent,
|
|
9671
|
+
{
|
|
9672
|
+
side: "right",
|
|
9673
|
+
className: "w-full sm:max-w-lg p-0 overflow-hidden",
|
|
9674
|
+
children: selectedDelivery ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9675
|
+
DeliveryDetailsView2,
|
|
9676
|
+
{
|
|
9677
|
+
delivery: selectedDelivery,
|
|
9678
|
+
week,
|
|
9679
|
+
onBack: () => setSelectedDelivery(null),
|
|
9680
|
+
onAddComment: onAddDeliveryComment ? (text) => {
|
|
9681
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9682
|
+
onAddDeliveryComment(supplier.id, weekKey, selectedDelivery.id, text);
|
|
9683
|
+
} : void 0
|
|
9684
|
+
}
|
|
9685
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9686
|
+
MainView2,
|
|
9687
|
+
{
|
|
9688
|
+
supplier,
|
|
9689
|
+
week,
|
|
9690
|
+
data,
|
|
9691
|
+
productionElements,
|
|
9692
|
+
previousProducedCount,
|
|
9693
|
+
onOpenProductionDialog: () => setProductionDialogOpen(true),
|
|
9694
|
+
onSelectDelivery: setSelectedDelivery,
|
|
9695
|
+
onAddProductionComment: onAddProductionComment ? (text) => {
|
|
9696
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9697
|
+
onAddProductionComment(supplier.id, weekKey, text);
|
|
9698
|
+
} : void 0
|
|
9699
|
+
}
|
|
9700
|
+
)
|
|
9701
|
+
}
|
|
9702
|
+
) }),
|
|
9703
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9704
|
+
ElementProductionDialog,
|
|
9705
|
+
{
|
|
9706
|
+
open: productionDialogOpen,
|
|
9707
|
+
onOpenChange: setProductionDialogOpen,
|
|
9708
|
+
elements: productionElements,
|
|
9709
|
+
onSave: handleProductionSave
|
|
9710
|
+
}
|
|
9711
|
+
)
|
|
9712
|
+
] });
|
|
9713
|
+
}
|
|
9714
|
+
function RowHeaderCell({
|
|
9715
|
+
className,
|
|
9716
|
+
data,
|
|
9717
|
+
showProgress = true,
|
|
9718
|
+
...props
|
|
9719
|
+
}) {
|
|
9720
|
+
const progressPercent = data.totalRequired > 0 ? Math.min(data.totalBooked / data.totalRequired * 100, 100) : 0;
|
|
9721
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9722
|
+
"div",
|
|
9723
|
+
{
|
|
9724
|
+
"data-slot": "row-header-cell",
|
|
9725
|
+
className: cn(
|
|
9726
|
+
"flex flex-col justify-center gap-1.5 py-2 px-3 min-w-[200px] h-[100px] bg-background",
|
|
9727
|
+
className
|
|
9728
|
+
),
|
|
9729
|
+
...props,
|
|
9730
|
+
children: [
|
|
9731
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
9732
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
9733
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: data.name }),
|
|
9734
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: data.typeCode })
|
|
9735
|
+
] }),
|
|
9736
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9737
|
+
Badge,
|
|
9738
|
+
{
|
|
9739
|
+
variant: "outline",
|
|
9740
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
9741
|
+
children: [
|
|
9742
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Flag, { className: "h-2.5 w-2.5" }),
|
|
9743
|
+
"Paint"
|
|
9744
|
+
]
|
|
9745
|
+
}
|
|
9746
|
+
)
|
|
9747
|
+
] }),
|
|
9748
|
+
showProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
9749
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9750
|
+
"div",
|
|
9751
|
+
{
|
|
9752
|
+
className: "h-full bg-primary rounded-full transition-all",
|
|
9753
|
+
style: { width: `${progressPercent}%` }
|
|
8194
9754
|
}
|
|
8195
9755
|
) }),
|
|
8196
9756
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-primary", children: [
|
|
@@ -8853,6 +10413,84 @@ function CalibrationTable({
|
|
|
8853
10413
|
() => prefixes.map((p) => ({ id: p.id, name: p.name })),
|
|
8854
10414
|
[prefixes]
|
|
8855
10415
|
);
|
|
10416
|
+
const insightMetrics = React27__namespace.useMemo(() => {
|
|
10417
|
+
let totalCalibrated = 0;
|
|
10418
|
+
let totalRequired = 0;
|
|
10419
|
+
for (const prefix of prefixes) {
|
|
10420
|
+
for (const weekKey in prefix.weeks) {
|
|
10421
|
+
const cell = prefix.weeks[weekKey];
|
|
10422
|
+
if (cell.planned > 0) {
|
|
10423
|
+
totalRequired += cell.planned;
|
|
10424
|
+
totalCalibrated += cell.entered ?? 0;
|
|
10425
|
+
}
|
|
10426
|
+
}
|
|
10427
|
+
}
|
|
10428
|
+
const completeness = totalRequired > 0 ? totalCalibrated / totalRequired * 100 : 0;
|
|
10429
|
+
const remaining = Math.max(0, totalRequired - totalCalibrated);
|
|
10430
|
+
return [
|
|
10431
|
+
{
|
|
10432
|
+
key: "calibrated",
|
|
10433
|
+
label: "calibrated",
|
|
10434
|
+
value: totalCalibrated,
|
|
10435
|
+
unit: "tons",
|
|
10436
|
+
icon: "factory",
|
|
10437
|
+
status: completeness >= 100 ? "success" : "normal"
|
|
10438
|
+
},
|
|
10439
|
+
{
|
|
10440
|
+
key: "remaining",
|
|
10441
|
+
label: "remaining",
|
|
10442
|
+
value: remaining,
|
|
10443
|
+
unit: "tons",
|
|
10444
|
+
icon: "factory",
|
|
10445
|
+
status: remaining > 0 ? "warning" : "success"
|
|
10446
|
+
},
|
|
10447
|
+
{
|
|
10448
|
+
key: "completeness",
|
|
10449
|
+
label: "complete",
|
|
10450
|
+
value: completeness,
|
|
10451
|
+
isPercentage: true,
|
|
10452
|
+
icon: "trending",
|
|
10453
|
+
status: completeness >= 100 ? "success" : completeness >= 50 ? "normal" : "warning"
|
|
10454
|
+
}
|
|
10455
|
+
];
|
|
10456
|
+
}, [prefixes]);
|
|
10457
|
+
const columnSummaryData = React27__namespace.useMemo(() => {
|
|
10458
|
+
return weeks.map((week) => {
|
|
10459
|
+
const weekKey = getWeekKey(week.startDate);
|
|
10460
|
+
let calibratedTons = 0;
|
|
10461
|
+
let requiredTons = 0;
|
|
10462
|
+
let hasShortfall = false;
|
|
10463
|
+
let allValid = true;
|
|
10464
|
+
for (const prefix of prefixes) {
|
|
10465
|
+
const cell = prefix.weeks[weekKey];
|
|
10466
|
+
if (cell) {
|
|
10467
|
+
requiredTons += cell.planned;
|
|
10468
|
+
calibratedTons += cell.entered ?? 0;
|
|
10469
|
+
if (cell.status === "shortfall") hasShortfall = true;
|
|
10470
|
+
if (cell.status !== "valid" && cell.planned > 0) allValid = false;
|
|
10471
|
+
}
|
|
10472
|
+
}
|
|
10473
|
+
let status2 = "normal";
|
|
10474
|
+
if (hasShortfall) {
|
|
10475
|
+
status2 = "critical";
|
|
10476
|
+
} else if (allValid && requiredTons > 0) {
|
|
10477
|
+
status2 = "complete";
|
|
10478
|
+
}
|
|
10479
|
+
return {
|
|
10480
|
+
columnKey: weekKey,
|
|
10481
|
+
primary: {
|
|
10482
|
+
value: calibratedTons,
|
|
10483
|
+
unit: "t",
|
|
10484
|
+
icon: "factory"
|
|
10485
|
+
},
|
|
10486
|
+
secondary: {
|
|
10487
|
+
value: requiredTons,
|
|
10488
|
+
unit: "t req"
|
|
10489
|
+
},
|
|
10490
|
+
status: status2
|
|
10491
|
+
};
|
|
10492
|
+
});
|
|
10493
|
+
}, [weeks, prefixes]);
|
|
8856
10494
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8857
10495
|
"div",
|
|
8858
10496
|
{
|
|
@@ -8863,6 +10501,7 @@ function CalibrationTable({
|
|
|
8863
10501
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: "Weekly Production Calibration" }),
|
|
8864
10502
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "Review required weekly production and confirm achievable output at the selected checkpoint." })
|
|
8865
10503
|
] }) }),
|
|
10504
|
+
/* @__PURE__ */ jsxRuntime.jsx(InsightBar, { metrics: insightMetrics }),
|
|
8866
10505
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8867
10506
|
showToolbar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
8868
10507
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8895,36 +10534,74 @@ function CalibrationTable({
|
|
|
8895
10534
|
style: { maxHeight },
|
|
8896
10535
|
children: [
|
|
8897
10536
|
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
|
|
8898
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8899
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
10537
|
+
/* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "sticky top-0 z-20", children: [
|
|
10538
|
+
/* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
10539
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: cn(
|
|
10540
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
10541
|
+
"border-r border-b border-border bg-sidebar",
|
|
10542
|
+
stickyRowHeader && "sticky left-0 z-30 min-w-[200px]",
|
|
10543
|
+
// Right shadow using Quantum token
|
|
10544
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
10545
|
+
), children: "Supplier / Scope" }),
|
|
10546
|
+
weeks.map((week) => {
|
|
10547
|
+
const weekKey = getWeekKey(week.startDate);
|
|
10548
|
+
const weekComments = getWeekComments(weekKey);
|
|
10549
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10550
|
+
"th",
|
|
10551
|
+
{
|
|
10552
|
+
className: "h-14 px-2 text-left align-middle border-r border-b border-border last:border-r-0 min-w-[220px] bg-sidebar",
|
|
10553
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10554
|
+
CalibrationWeekHeader,
|
|
10555
|
+
{
|
|
10556
|
+
week,
|
|
10557
|
+
comments: weekComments,
|
|
10558
|
+
showCommentButton: true,
|
|
10559
|
+
availablePrefixes,
|
|
10560
|
+
onAddComment: (text, prefixId, prefixName) => handleAddWeekComment(weekKey, text, prefixId)
|
|
10561
|
+
}
|
|
10562
|
+
)
|
|
10563
|
+
},
|
|
10564
|
+
weekKey
|
|
10565
|
+
);
|
|
10566
|
+
})
|
|
10567
|
+
] }),
|
|
10568
|
+
/* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
10569
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: cn(
|
|
10570
|
+
"h-auto px-3 py-1.5 text-left align-middle",
|
|
10571
|
+
"border-r border-b border-border bg-muted/30",
|
|
10572
|
+
stickyRowHeader && "sticky left-0 z-30 min-w-[200px]",
|
|
10573
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
10574
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide", children: "Summary" }) }),
|
|
10575
|
+
columnSummaryData.map((summary) => {
|
|
10576
|
+
const statusBg = summary.status === "complete" ? "bg-green-50/50 dark:bg-green-950/30" : summary.status === "critical" ? "bg-red-50/50 dark:bg-red-950/30" : "bg-muted/30";
|
|
10577
|
+
const statusText = summary.status === "complete" ? "text-green-700 dark:text-green-300" : summary.status === "critical" ? "text-red-700 dark:text-red-300" : "text-muted-foreground";
|
|
10578
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10579
|
+
"th",
|
|
10580
|
+
{
|
|
10581
|
+
className: cn(
|
|
10582
|
+
"h-auto px-2 py-1.5 text-left align-middle",
|
|
10583
|
+
"border-r border-b border-border last:border-r-0 min-w-[220px]",
|
|
10584
|
+
statusBg
|
|
10585
|
+
),
|
|
10586
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
10587
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
10588
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: cn("h-3 w-3", statusText) }),
|
|
10589
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-xs font-medium tabular-nums", statusText), children: [
|
|
10590
|
+
summary.primary?.value.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
10591
|
+
" t"
|
|
10592
|
+
] })
|
|
10593
|
+
] }),
|
|
10594
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground tabular-nums", children: [
|
|
10595
|
+
summary.secondary?.value.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
10596
|
+
" t req"
|
|
10597
|
+
] })
|
|
10598
|
+
] })
|
|
10599
|
+
},
|
|
10600
|
+
summary.columnKey
|
|
10601
|
+
);
|
|
10602
|
+
})
|
|
10603
|
+
] })
|
|
10604
|
+
] }),
|
|
8928
10605
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-background", children: paginatedPrefixes.length > 0 ? paginatedPrefixes.map((prefix) => {
|
|
8929
10606
|
const sortedWeekKeys = weeks.map((w) => getWeekKey(w.startDate));
|
|
8930
10607
|
let hasDeficit = false;
|
|
@@ -9423,40 +11100,40 @@ function groupDeliveriesByPrefixAndDay(deliveries) {
|
|
|
9423
11100
|
}
|
|
9424
11101
|
return grouped;
|
|
9425
11102
|
}
|
|
9426
|
-
function
|
|
11103
|
+
function getCardStyles(state, hasRisk) {
|
|
9427
11104
|
if (hasRisk) {
|
|
9428
11105
|
return {
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
iconColor:
|
|
9433
|
-
|
|
11106
|
+
fill: statusCellFillClasses.risk.combined,
|
|
11107
|
+
titleColor: statusCellTextClasses.risk.title,
|
|
11108
|
+
subtitleColor: statusCellTextClasses.risk.subtitle,
|
|
11109
|
+
iconColor: statusCellTextClasses.risk.icon,
|
|
11110
|
+
opacity: ""
|
|
9434
11111
|
};
|
|
9435
11112
|
}
|
|
9436
11113
|
switch (state) {
|
|
9437
11114
|
case "sent":
|
|
9438
11115
|
return {
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
iconColor:
|
|
9443
|
-
|
|
11116
|
+
fill: statusCellFillClasses.shipped.combined,
|
|
11117
|
+
titleColor: statusCellTextClasses.shipped.title,
|
|
11118
|
+
subtitleColor: statusCellTextClasses.shipped.subtitle,
|
|
11119
|
+
iconColor: statusCellTextClasses.shipped.icon,
|
|
11120
|
+
opacity: "opacity-75"
|
|
9444
11121
|
};
|
|
9445
11122
|
case "ready":
|
|
9446
11123
|
return {
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
iconColor:
|
|
9451
|
-
|
|
11124
|
+
fill: statusCellFillClasses.ready.combined,
|
|
11125
|
+
titleColor: statusCellTextClasses.ready.title,
|
|
11126
|
+
subtitleColor: statusCellTextClasses.ready.subtitle,
|
|
11127
|
+
iconColor: statusCellTextClasses.ready.icon,
|
|
11128
|
+
opacity: ""
|
|
9452
11129
|
};
|
|
9453
11130
|
default:
|
|
9454
11131
|
return {
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
iconColor:
|
|
9459
|
-
|
|
11132
|
+
fill: statusCellFillClasses.normal.combined,
|
|
11133
|
+
titleColor: statusCellTextClasses.normal.title,
|
|
11134
|
+
subtitleColor: statusCellTextClasses.normal.subtitle,
|
|
11135
|
+
iconColor: statusCellTextClasses.normal.icon,
|
|
11136
|
+
opacity: ""
|
|
9460
11137
|
};
|
|
9461
11138
|
}
|
|
9462
11139
|
}
|
|
@@ -9466,55 +11143,10 @@ function DeliveryBadge({
|
|
|
9466
11143
|
onCommentClick,
|
|
9467
11144
|
className
|
|
9468
11145
|
}) {
|
|
9469
|
-
const [isHovered, setIsHovered] = React27__namespace.useState(false);
|
|
9470
11146
|
const hasComments = delivery.comments.length > 0;
|
|
9471
11147
|
const visualState = getDeliveryVisualState(delivery);
|
|
9472
|
-
const styles =
|
|
9473
|
-
const
|
|
9474
|
-
const prefixSet = /* @__PURE__ */ new Set();
|
|
9475
|
-
if (delivery.elements && delivery.elements.length > 0) {
|
|
9476
|
-
for (const element of delivery.elements) {
|
|
9477
|
-
if (element.prefix) {
|
|
9478
|
-
prefixSet.add(element.prefix);
|
|
9479
|
-
}
|
|
9480
|
-
}
|
|
9481
|
-
}
|
|
9482
|
-
if (prefixSet.size === 0 && delivery.prefixScope) {
|
|
9483
|
-
prefixSet.add(delivery.prefixScope);
|
|
9484
|
-
}
|
|
9485
|
-
const prefixes = Array.from(prefixSet);
|
|
9486
|
-
if (prefixes.length === 0) {
|
|
9487
|
-
return delivery.label;
|
|
9488
|
-
}
|
|
9489
|
-
if (prefixes.length > 3) {
|
|
9490
|
-
return `${prefixes.slice(0, 3).join(" \xB7 ")} \xB7 +${prefixes.length - 3}`;
|
|
9491
|
-
}
|
|
9492
|
-
return prefixes.join(" \xB7 ");
|
|
9493
|
-
}, [delivery]);
|
|
9494
|
-
const productionProgress = React27__namespace.useMemo(() => {
|
|
9495
|
-
if (delivery.producedTons !== void 0 && delivery.totalTons !== void 0 && delivery.totalTons > 0) {
|
|
9496
|
-
return Math.min(delivery.producedTons / delivery.totalTons * 100, 100);
|
|
9497
|
-
}
|
|
9498
|
-
if (delivery.producedCount !== void 0 && delivery.totalCount !== void 0 && delivery.totalCount > 0) {
|
|
9499
|
-
return Math.min(delivery.producedCount / delivery.totalCount * 100, 100);
|
|
9500
|
-
}
|
|
9501
|
-
if (delivery.loadedCount !== void 0 && delivery.totalCount !== void 0 && delivery.totalCount > 0) {
|
|
9502
|
-
return Math.min(delivery.loadedCount / delivery.totalCount * 100, 100);
|
|
9503
|
-
}
|
|
9504
|
-
return 0;
|
|
9505
|
-
}, [delivery]);
|
|
9506
|
-
const productionDisplay = React27__namespace.useMemo(() => {
|
|
9507
|
-
if (delivery.producedTons !== void 0 && delivery.totalTons !== void 0) {
|
|
9508
|
-
return `${delivery.producedTons}/${delivery.totalTons}t`;
|
|
9509
|
-
}
|
|
9510
|
-
if (delivery.producedCount !== void 0 && delivery.totalCount !== void 0) {
|
|
9511
|
-
return `${delivery.producedCount}/${delivery.totalCount}`;
|
|
9512
|
-
}
|
|
9513
|
-
if (delivery.loadedCount !== void 0 && delivery.totalCount !== void 0) {
|
|
9514
|
-
return `${delivery.loadedCount}/${delivery.totalCount}`;
|
|
9515
|
-
}
|
|
9516
|
-
return null;
|
|
9517
|
-
}, [delivery]);
|
|
11148
|
+
const styles = getCardStyles(visualState, delivery.hasProductionRisk ?? false);
|
|
11149
|
+
const projectName = delivery.destination || delivery.label;
|
|
9518
11150
|
const handleClick = (e) => {
|
|
9519
11151
|
e.stopPropagation();
|
|
9520
11152
|
onClick?.();
|
|
@@ -9530,38 +11162,22 @@ function DeliveryBadge({
|
|
|
9530
11162
|
e.stopPropagation();
|
|
9531
11163
|
onCommentClick?.();
|
|
9532
11164
|
};
|
|
9533
|
-
const amountColorClass = React27__namespace.useMemo(() => {
|
|
9534
|
-
if (visualState === "sent") {
|
|
9535
|
-
return "text-muted-foreground/40";
|
|
9536
|
-
}
|
|
9537
|
-
if (delivery.isReadyToUnload) {
|
|
9538
|
-
return "text-green-600 dark:text-green-400";
|
|
9539
|
-
}
|
|
9540
|
-
if (delivery.hasProductionRisk) {
|
|
9541
|
-
return "text-red-600 dark:text-red-400";
|
|
9542
|
-
}
|
|
9543
|
-
return "text-muted-foreground";
|
|
9544
|
-
}, [visualState, delivery.isReadyToUnload, delivery.hasProductionRisk]);
|
|
9545
11165
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9546
11166
|
"div",
|
|
9547
11167
|
{
|
|
9548
11168
|
className: cn(
|
|
9549
11169
|
// Position relative for comment button
|
|
9550
11170
|
"relative",
|
|
9551
|
-
// Full-width in cell,
|
|
9552
|
-
"w-full rounded-
|
|
9553
|
-
//
|
|
9554
|
-
|
|
9555
|
-
// -
|
|
9556
|
-
//
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
"border border-border",
|
|
9562
|
-
// Left stroke for status
|
|
9563
|
-
styles.stroke,
|
|
9564
|
-
// Interactive states (reduced for sent state)
|
|
11171
|
+
// Full-width in cell, small radius (matching planning cards)
|
|
11172
|
+
"w-full rounded-lg",
|
|
11173
|
+
// Compact sizing - min-h-[72px], p-4 (j3m.spacing.m)
|
|
11174
|
+
"min-h-[72px] p-4",
|
|
11175
|
+
// FULL-CARD STATUS FILL - uses shared calibration/planning tokens
|
|
11176
|
+
// This is the key change: status fill on outermost container
|
|
11177
|
+
styles.fill,
|
|
11178
|
+
// Opacity for shipped state
|
|
11179
|
+
styles.opacity,
|
|
11180
|
+
// Interactive states (disabled hover lift for shipped)
|
|
9565
11181
|
"transition-all duration-200 ease-out",
|
|
9566
11182
|
visualState !== "sent" && "hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
9567
11183
|
className
|
|
@@ -9574,10 +11190,12 @@ function DeliveryBadge({
|
|
|
9574
11190
|
variant: "ghost",
|
|
9575
11191
|
size: "icon",
|
|
9576
11192
|
className: cn(
|
|
9577
|
-
"absolute top-
|
|
11193
|
+
"absolute top-1.5 right-1.5",
|
|
9578
11194
|
// 44px touch target for accessibility
|
|
9579
11195
|
"h-11 w-11",
|
|
9580
11196
|
"rounded-full",
|
|
11197
|
+
// Subtle background for visibility on colored fills
|
|
11198
|
+
"bg-background/50 hover:bg-background/80",
|
|
9581
11199
|
hasComments && "text-primary"
|
|
9582
11200
|
),
|
|
9583
11201
|
onClick: handleCommentClick,
|
|
@@ -9600,13 +11218,11 @@ function DeliveryBadge({
|
|
|
9600
11218
|
type: "button",
|
|
9601
11219
|
onClick: handleClick,
|
|
9602
11220
|
onKeyDown: handleKeyDown,
|
|
9603
|
-
onMouseEnter: () => setIsHovered(true),
|
|
9604
|
-
onMouseLeave: () => setIsHovered(false),
|
|
9605
11221
|
className: cn(
|
|
9606
11222
|
// Full width, no background (inherits from parent)
|
|
9607
11223
|
"w-full bg-transparent text-left",
|
|
9608
11224
|
// Layout - vertical stack
|
|
9609
|
-
"flex flex-col
|
|
11225
|
+
"flex flex-col justify-between h-full min-h-[40px]",
|
|
9610
11226
|
// Interactive states
|
|
9611
11227
|
"cursor-pointer",
|
|
9612
11228
|
"active:translate-y-0 active:shadow-sm",
|
|
@@ -9614,33 +11230,20 @@ function DeliveryBadge({
|
|
|
9614
11230
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1"
|
|
9615
11231
|
),
|
|
9616
11232
|
children: [
|
|
9617
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
9618
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
), children: delivery.supplierName })
|
|
11233
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 pr-12", children: [
|
|
11234
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
11235
|
+
"text-sm font-semibold leading-tight line-clamp-2",
|
|
11236
|
+
styles.titleColor
|
|
11237
|
+
), children: projectName }),
|
|
11238
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: cn("h-4 w-4 shrink-0 mt-0.5", styles.iconColor) })
|
|
9624
11239
|
] }),
|
|
9625
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9626
|
-
"
|
|
9627
|
-
|
|
9628
|
-
className: cn("
|
|
9629
|
-
style: { width: `${productionProgress}%` }
|
|
9630
|
-
}
|
|
9631
|
-
) }) }),
|
|
9632
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
9633
|
-
productionDisplay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
9634
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: cn("h-3 w-3 shrink-0", styles.iconColor) }),
|
|
9635
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
9636
|
-
"text-[11px] tabular-nums font-medium",
|
|
9637
|
-
amountColorClass
|
|
9638
|
-
), children: productionDisplay })
|
|
11240
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 mt-2", children: [
|
|
11241
|
+
visualState === "sent" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11242
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-3.5 w-3.5 shrink-0", styles.iconColor) }),
|
|
11243
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-medium uppercase tracking-wide", styles.subtitleColor), children: "Shipped" })
|
|
9639
11244
|
] }),
|
|
9640
|
-
visualState === "
|
|
9641
|
-
|
|
9642
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground/50 uppercase tracking-wide", children: "Sent" })
|
|
9643
|
-
] })
|
|
11245
|
+
visualState === "ready" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-semibold uppercase tracking-wide", styles.subtitleColor), children: "Ready" }),
|
|
11246
|
+
delivery.hasProductionRisk && visualState !== "sent" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-semibold uppercase tracking-wide", styles.subtitleColor), children: "At Risk" })
|
|
9644
11247
|
] })
|
|
9645
11248
|
]
|
|
9646
11249
|
}
|
|
@@ -9649,6 +11252,62 @@ function DeliveryBadge({
|
|
|
9649
11252
|
}
|
|
9650
11253
|
);
|
|
9651
11254
|
}
|
|
11255
|
+
function isShippedDelivery(delivery) {
|
|
11256
|
+
return delivery.status === "shipped" || delivery.status === "delivered";
|
|
11257
|
+
}
|
|
11258
|
+
function ShippedDeliveriesToggle({
|
|
11259
|
+
shippedDeliveries,
|
|
11260
|
+
isOpen,
|
|
11261
|
+
onToggle,
|
|
11262
|
+
onDeliveryClick,
|
|
11263
|
+
onDeliveryCommentClick
|
|
11264
|
+
}) {
|
|
11265
|
+
if (shippedDeliveries.length === 0) return null;
|
|
11266
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: isOpen, onOpenChange: onToggle, children: [
|
|
11267
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11268
|
+
"button",
|
|
11269
|
+
{
|
|
11270
|
+
type: "button",
|
|
11271
|
+
className: cn(
|
|
11272
|
+
"w-full flex items-center justify-between gap-2",
|
|
11273
|
+
"min-h-[44px] px-3 py-2",
|
|
11274
|
+
"rounded-md",
|
|
11275
|
+
"text-xs text-muted-foreground",
|
|
11276
|
+
"hover:bg-muted/50 transition-colors",
|
|
11277
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
|
|
11278
|
+
),
|
|
11279
|
+
children: [
|
|
11280
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11281
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5 text-green-600 dark:text-green-400" }),
|
|
11282
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
11283
|
+
"Shipped (",
|
|
11284
|
+
shippedDeliveries.length,
|
|
11285
|
+
")"
|
|
11286
|
+
] })
|
|
11287
|
+
] }),
|
|
11288
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11289
|
+
lucideReact.ChevronDown,
|
|
11290
|
+
{
|
|
11291
|
+
className: cn(
|
|
11292
|
+
"h-4 w-4 transition-transform duration-200",
|
|
11293
|
+
isOpen && "rotate-180"
|
|
11294
|
+
)
|
|
11295
|
+
}
|
|
11296
|
+
)
|
|
11297
|
+
]
|
|
11298
|
+
}
|
|
11299
|
+
) }),
|
|
11300
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3 pt-2", children: shippedDeliveries.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11301
|
+
DeliveryBadge,
|
|
11302
|
+
{
|
|
11303
|
+
delivery,
|
|
11304
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
11305
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
11306
|
+
},
|
|
11307
|
+
delivery.id
|
|
11308
|
+
)) }) })
|
|
11309
|
+
] });
|
|
11310
|
+
}
|
|
9652
11311
|
function WeeklyLoadingView({
|
|
9653
11312
|
week,
|
|
9654
11313
|
deliveries,
|
|
@@ -9658,6 +11317,24 @@ function WeeklyLoadingView({
|
|
|
9658
11317
|
showNavigation = true,
|
|
9659
11318
|
className
|
|
9660
11319
|
}) {
|
|
11320
|
+
const [shippedOpenState, setShippedOpenState] = React27__namespace.useState({
|
|
11321
|
+
1: false,
|
|
11322
|
+
// Monday
|
|
11323
|
+
2: false,
|
|
11324
|
+
// Tuesday
|
|
11325
|
+
3: false,
|
|
11326
|
+
// Wednesday
|
|
11327
|
+
4: false,
|
|
11328
|
+
// Thursday
|
|
11329
|
+
5: false
|
|
11330
|
+
// Friday
|
|
11331
|
+
});
|
|
11332
|
+
const toggleShippedForDay = (dayOfWeek) => {
|
|
11333
|
+
setShippedOpenState((prev) => ({
|
|
11334
|
+
...prev,
|
|
11335
|
+
[dayOfWeek]: !prev[dayOfWeek]
|
|
11336
|
+
}));
|
|
11337
|
+
};
|
|
9661
11338
|
const weekDays = React27__namespace.useMemo(() => {
|
|
9662
11339
|
const days = [];
|
|
9663
11340
|
for (let i = 0; i < 5; i++) {
|
|
@@ -9673,19 +11350,36 @@ function WeeklyLoadingView({
|
|
|
9673
11350
|
const deliveriesByDay = React27__namespace.useMemo(() => {
|
|
9674
11351
|
const grouped = /* @__PURE__ */ new Map();
|
|
9675
11352
|
for (let i = 1; i <= 5; i++) {
|
|
9676
|
-
grouped.set(i, []);
|
|
11353
|
+
grouped.set(i, { pending: [], shipped: [] });
|
|
9677
11354
|
}
|
|
9678
11355
|
for (const delivery of deliveries) {
|
|
9679
11356
|
const dayOfWeek = delivery.date.getDay();
|
|
9680
11357
|
if (dayOfWeek >= 1 && dayOfWeek <= 5) {
|
|
9681
|
-
const
|
|
9682
|
-
|
|
9683
|
-
|
|
11358
|
+
const dayData = grouped.get(dayOfWeek);
|
|
11359
|
+
if (isShippedDelivery(delivery)) {
|
|
11360
|
+
dayData.shipped.push(delivery);
|
|
11361
|
+
} else {
|
|
11362
|
+
dayData.pending.push(delivery);
|
|
11363
|
+
}
|
|
9684
11364
|
}
|
|
9685
11365
|
}
|
|
9686
11366
|
return grouped;
|
|
9687
11367
|
}, [deliveries]);
|
|
9688
|
-
const
|
|
11368
|
+
const totalPendingDeliveries = deliveries.filter((d) => !isShippedDelivery(d)).length;
|
|
11369
|
+
const totalShippedDeliveries = deliveries.filter((d) => isShippedDelivery(d)).length;
|
|
11370
|
+
const daySummaryData = React27__namespace.useMemo(() => {
|
|
11371
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
11372
|
+
for (let i = 1; i <= 5; i++) {
|
|
11373
|
+
const dayData = deliveriesByDay.get(i) ?? { pending: [], shipped: [] };
|
|
11374
|
+
const allDayDeliveries = [...dayData.pending, ...dayData.shipped];
|
|
11375
|
+
summaries.set(i, {
|
|
11376
|
+
deliveries: allDayDeliveries.length,
|
|
11377
|
+
tonsRequired: allDayDeliveries.reduce((sum, d) => sum + (d.totalTons ?? 0), 0),
|
|
11378
|
+
tonsProduced: allDayDeliveries.reduce((sum, d) => sum + (d.producedTons ?? 0), 0)
|
|
11379
|
+
});
|
|
11380
|
+
}
|
|
11381
|
+
return summaries;
|
|
11382
|
+
}, [deliveriesByDay]);
|
|
9689
11383
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col", className), children: [
|
|
9690
11384
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 border-b border-border p-4 lg:flex-row lg:items-center lg:justify-between", children: [
|
|
9691
11385
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
@@ -9702,9 +11396,9 @@ function WeeklyLoadingView({
|
|
|
9702
11396
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
9703
11397
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: week.dateRange }),
|
|
9704
11398
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
9705
|
-
|
|
9706
|
-
" ",
|
|
9707
|
-
|
|
11399
|
+
totalPendingDeliveries,
|
|
11400
|
+
" pending",
|
|
11401
|
+
totalShippedDeliveries > 0 && `, ${totalShippedDeliveries} shipped`
|
|
9708
11402
|
] })
|
|
9709
11403
|
] })
|
|
9710
11404
|
] }),
|
|
@@ -9770,9 +11464,48 @@ function WeeklyLoadingView({
|
|
|
9770
11464
|
},
|
|
9771
11465
|
dayOfWeek
|
|
9772
11466
|
)) }),
|
|
11467
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-5 border-b border-border", children: weekDays.map(({ dayOfWeek, isToday: dayIsToday }) => {
|
|
11468
|
+
const summary = daySummaryData.get(dayOfWeek) ?? { deliveries: 0, tonsRequired: 0, tonsProduced: 0 };
|
|
11469
|
+
const productionComplete = summary.tonsRequired > 0 && summary.tonsProduced >= summary.tonsRequired;
|
|
11470
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11471
|
+
"div",
|
|
11472
|
+
{
|
|
11473
|
+
className: cn(
|
|
11474
|
+
"flex flex-col gap-0.5 py-1.5 px-2",
|
|
11475
|
+
productionComplete ? "bg-green-50/50 dark:bg-green-950/30" : "bg-muted/20",
|
|
11476
|
+
dayIsToday && "bg-primary/5"
|
|
11477
|
+
),
|
|
11478
|
+
children: [
|
|
11479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11480
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3 w-3 text-muted-foreground" }),
|
|
11481
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium tabular-nums text-muted-foreground", children: summary.deliveries })
|
|
11482
|
+
] }),
|
|
11483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11484
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: cn(
|
|
11485
|
+
"h-3 w-3",
|
|
11486
|
+
productionComplete ? "text-green-600 dark:text-green-400" : "text-muted-foreground"
|
|
11487
|
+
) }),
|
|
11488
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
11489
|
+
"text-[10px] tabular-nums",
|
|
11490
|
+
productionComplete ? "text-green-700 dark:text-green-300" : "text-muted-foreground"
|
|
11491
|
+
), children: [
|
|
11492
|
+
summary.tonsProduced.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
11493
|
+
"/",
|
|
11494
|
+
summary.tonsRequired.toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
11495
|
+
" t"
|
|
11496
|
+
] })
|
|
11497
|
+
] })
|
|
11498
|
+
]
|
|
11499
|
+
},
|
|
11500
|
+
dayOfWeek
|
|
11501
|
+
);
|
|
11502
|
+
}) }),
|
|
9773
11503
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-5", children: weekDays.map(({ dayOfWeek, isToday: dayIsToday }) => {
|
|
9774
|
-
const
|
|
9775
|
-
|
|
11504
|
+
const dayData = deliveriesByDay.get(dayOfWeek) ?? { pending: [], shipped: [] };
|
|
11505
|
+
const hasPending = dayData.pending.length > 0;
|
|
11506
|
+
const hasShipped = dayData.shipped.length > 0;
|
|
11507
|
+
const isEmpty = !hasPending && !hasShipped;
|
|
11508
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9776
11509
|
"div",
|
|
9777
11510
|
{
|
|
9778
11511
|
className: cn(
|
|
@@ -9780,22 +11513,39 @@ function WeeklyLoadingView({
|
|
|
9780
11513
|
"flex flex-col p-3",
|
|
9781
11514
|
dayIsToday && "bg-primary/5"
|
|
9782
11515
|
),
|
|
9783
|
-
children:
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
11516
|
+
children: [
|
|
11517
|
+
hasPending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: dayData.pending.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11518
|
+
DeliveryBadge,
|
|
11519
|
+
{
|
|
11520
|
+
delivery,
|
|
11521
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
11522
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
11523
|
+
},
|
|
11524
|
+
delivery.id
|
|
11525
|
+
)) }),
|
|
11526
|
+
hasShipped && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(hasPending && "mt-3"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11527
|
+
ShippedDeliveriesToggle,
|
|
11528
|
+
{
|
|
11529
|
+
shippedDeliveries: dayData.shipped,
|
|
11530
|
+
isOpen: shippedOpenState[dayOfWeek] ?? false,
|
|
11531
|
+
onToggle: () => toggleShippedForDay(dayOfWeek),
|
|
11532
|
+
onDeliveryClick,
|
|
11533
|
+
onDeliveryCommentClick
|
|
11534
|
+
}
|
|
11535
|
+
) }),
|
|
11536
|
+
isEmpty && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-6 text-sm text-muted-foreground/40", children: "\u2014" })
|
|
11537
|
+
]
|
|
9792
11538
|
},
|
|
9793
11539
|
dayOfWeek
|
|
9794
11540
|
);
|
|
9795
11541
|
}) })
|
|
9796
11542
|
] }),
|
|
9797
11543
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden divide-y divide-border", children: weekDays.map(({ date, dayOfWeek, isToday: dayIsToday }) => {
|
|
9798
|
-
const
|
|
11544
|
+
const dayData = deliveriesByDay.get(dayOfWeek) ?? { pending: [], shipped: [] };
|
|
11545
|
+
const hasPending = dayData.pending.length > 0;
|
|
11546
|
+
const hasShipped = dayData.shipped.length > 0;
|
|
11547
|
+
const isEmpty = !hasPending && !hasShipped;
|
|
11548
|
+
dayData.pending.length + dayData.shipped.length;
|
|
9799
11549
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9800
11550
|
"div",
|
|
9801
11551
|
{
|
|
@@ -9818,20 +11568,33 @@ function WeeklyLoadingView({
|
|
|
9818
11568
|
dayIsToday && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-primary font-medium bg-primary/10 px-2 py-0.5 rounded", children: "Today" })
|
|
9819
11569
|
] }),
|
|
9820
11570
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
9821
|
-
|
|
9822
|
-
" ",
|
|
9823
|
-
|
|
11571
|
+
dayData.pending.length,
|
|
11572
|
+
" pending",
|
|
11573
|
+
hasShipped && `, ${dayData.shipped.length} shipped`
|
|
9824
11574
|
] })
|
|
9825
11575
|
] }),
|
|
9826
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
11576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 p-3 pt-0", children: [
|
|
11577
|
+
hasPending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: dayData.pending.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11578
|
+
DeliveryBadge,
|
|
11579
|
+
{
|
|
11580
|
+
delivery,
|
|
11581
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
11582
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
11583
|
+
},
|
|
11584
|
+
delivery.id
|
|
11585
|
+
)) }),
|
|
11586
|
+
hasShipped && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11587
|
+
ShippedDeliveriesToggle,
|
|
11588
|
+
{
|
|
11589
|
+
shippedDeliveries: dayData.shipped,
|
|
11590
|
+
isOpen: shippedOpenState[dayOfWeek] ?? false,
|
|
11591
|
+
onToggle: () => toggleShippedForDay(dayOfWeek),
|
|
11592
|
+
onDeliveryClick,
|
|
11593
|
+
onDeliveryCommentClick
|
|
11594
|
+
}
|
|
11595
|
+
),
|
|
11596
|
+
isEmpty && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground/40 py-4 text-center", children: "\u2014" })
|
|
11597
|
+
] })
|
|
9835
11598
|
]
|
|
9836
11599
|
},
|
|
9837
11600
|
dayOfWeek
|
|
@@ -9840,36 +11603,63 @@ function WeeklyLoadingView({
|
|
|
9840
11603
|
] })
|
|
9841
11604
|
] });
|
|
9842
11605
|
}
|
|
9843
|
-
function
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
11606
|
+
function getTimelineState(delivery) {
|
|
11607
|
+
const isShipped = delivery.status === "shipped" || delivery.status === "delivered";
|
|
11608
|
+
const isReady = delivery.isReadyToUnload ?? false;
|
|
11609
|
+
const hasProductionData = delivery.producedCount !== void 0 || delivery.producedTons !== void 0;
|
|
11610
|
+
if (isShipped) {
|
|
11611
|
+
return {
|
|
11612
|
+
currentStep: "delivery",
|
|
11613
|
+
documentState: "completed",
|
|
11614
|
+
productionState: "completed",
|
|
11615
|
+
deliveryState: "completed",
|
|
11616
|
+
isReady: true,
|
|
11617
|
+
currentStepLabel: "Delivery",
|
|
11618
|
+
reason: "Delivery completed"
|
|
11619
|
+
};
|
|
9856
11620
|
}
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
11621
|
+
if (isReady) {
|
|
11622
|
+
return {
|
|
11623
|
+
currentStep: "delivery",
|
|
11624
|
+
documentState: "completed",
|
|
11625
|
+
productionState: "completed",
|
|
11626
|
+
deliveryState: "current",
|
|
11627
|
+
isReady: true,
|
|
11628
|
+
currentStepLabel: "Delivery",
|
|
11629
|
+
reason: "All prerequisites complete"
|
|
11630
|
+
};
|
|
11631
|
+
}
|
|
11632
|
+
if (hasProductionData) {
|
|
11633
|
+
return {
|
|
11634
|
+
currentStep: "production",
|
|
11635
|
+
documentState: "completed",
|
|
11636
|
+
productionState: "current",
|
|
11637
|
+
deliveryState: "upcoming",
|
|
11638
|
+
isReady: false,
|
|
11639
|
+
currentStepLabel: "Production",
|
|
11640
|
+
reason: delivery.hasProductionRisk ? delivery.riskReason || "Production delay risk" : "Not all items have been produced"
|
|
11641
|
+
};
|
|
11642
|
+
}
|
|
11643
|
+
if (delivery.status === "planned") {
|
|
11644
|
+
return {
|
|
11645
|
+
currentStep: "document",
|
|
11646
|
+
documentState: "current",
|
|
11647
|
+
productionState: "upcoming",
|
|
11648
|
+
deliveryState: "upcoming",
|
|
11649
|
+
isReady: false,
|
|
11650
|
+
currentStepLabel: "Document",
|
|
11651
|
+
reason: "Waiting for document approval"
|
|
11652
|
+
};
|
|
9872
11653
|
}
|
|
11654
|
+
return {
|
|
11655
|
+
currentStep: "production",
|
|
11656
|
+
documentState: "completed",
|
|
11657
|
+
productionState: "current",
|
|
11658
|
+
deliveryState: "upcoming",
|
|
11659
|
+
isReady: false,
|
|
11660
|
+
currentStepLabel: "Production",
|
|
11661
|
+
reason: "Production status pending"
|
|
11662
|
+
};
|
|
9873
11663
|
}
|
|
9874
11664
|
function getElementStatusBadgeClasses(status) {
|
|
9875
11665
|
switch (status) {
|
|
@@ -9885,6 +11675,166 @@ function getElementStatusBadgeClasses(status) {
|
|
|
9885
11675
|
return "border-muted-foreground/50 text-muted-foreground";
|
|
9886
11676
|
}
|
|
9887
11677
|
}
|
|
11678
|
+
var TIMELINE_STEPS = [
|
|
11679
|
+
{ id: "document", label: "Document", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "h-4 w-4" }) },
|
|
11680
|
+
{ id: "production", label: "Production", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-4 w-4" }) },
|
|
11681
|
+
{ id: "delivery", label: "Delivery", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4" }) }
|
|
11682
|
+
];
|
|
11683
|
+
function getStepStyles(state) {
|
|
11684
|
+
switch (state) {
|
|
11685
|
+
case "completed":
|
|
11686
|
+
return {
|
|
11687
|
+
dot: "bg-green-500/20 border-green-500",
|
|
11688
|
+
icon: "text-green-600 dark:text-green-400",
|
|
11689
|
+
label: "text-muted-foreground",
|
|
11690
|
+
line: "bg-green-500"
|
|
11691
|
+
};
|
|
11692
|
+
case "current":
|
|
11693
|
+
return {
|
|
11694
|
+
dot: "bg-primary/20 border-primary",
|
|
11695
|
+
icon: "text-primary",
|
|
11696
|
+
label: "text-foreground font-semibold",
|
|
11697
|
+
line: "bg-border"
|
|
11698
|
+
};
|
|
11699
|
+
case "upcoming":
|
|
11700
|
+
default:
|
|
11701
|
+
return {
|
|
11702
|
+
dot: "bg-muted border-border",
|
|
11703
|
+
icon: "text-muted-foreground/50",
|
|
11704
|
+
label: "text-muted-foreground/50",
|
|
11705
|
+
line: "bg-border"
|
|
11706
|
+
};
|
|
11707
|
+
}
|
|
11708
|
+
}
|
|
11709
|
+
function DeliveryTimeline({ timelineState }) {
|
|
11710
|
+
const getStateForStep = (stepId) => {
|
|
11711
|
+
switch (stepId) {
|
|
11712
|
+
case "document":
|
|
11713
|
+
return timelineState.documentState;
|
|
11714
|
+
case "production":
|
|
11715
|
+
return timelineState.productionState;
|
|
11716
|
+
case "delivery":
|
|
11717
|
+
return timelineState.deliveryState;
|
|
11718
|
+
}
|
|
11719
|
+
};
|
|
11720
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between w-full", children: TIMELINE_STEPS.map((step, index) => {
|
|
11721
|
+
const state = getStateForStep(step.id);
|
|
11722
|
+
const styles = getStepStyles(state);
|
|
11723
|
+
const isLast = index === TIMELINE_STEPS.length - 1;
|
|
11724
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React27__namespace.Fragment, { children: [
|
|
11725
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
11726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11727
|
+
"div",
|
|
11728
|
+
{
|
|
11729
|
+
className: cn(
|
|
11730
|
+
"flex items-center justify-center",
|
|
11731
|
+
"h-10 w-10 rounded-full border-2",
|
|
11732
|
+
"transition-colors duration-200",
|
|
11733
|
+
styles.dot
|
|
11734
|
+
),
|
|
11735
|
+
children: state === "completed" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-4 w-4", styles.icon) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.icon, children: step.icon })
|
|
11736
|
+
}
|
|
11737
|
+
),
|
|
11738
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs", styles.label), children: step.label })
|
|
11739
|
+
] }),
|
|
11740
|
+
!isLast && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 mx-2 mb-6", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11741
|
+
"div",
|
|
11742
|
+
{
|
|
11743
|
+
className: cn(
|
|
11744
|
+
"h-0.5 w-full rounded-full",
|
|
11745
|
+
styles.line
|
|
11746
|
+
)
|
|
11747
|
+
}
|
|
11748
|
+
) })
|
|
11749
|
+
] }, step.id);
|
|
11750
|
+
}) });
|
|
11751
|
+
}
|
|
11752
|
+
function PackingStatusBadge({
|
|
11753
|
+
timelineState,
|
|
11754
|
+
hasRisk
|
|
11755
|
+
}) {
|
|
11756
|
+
const getPackingStatus = () => {
|
|
11757
|
+
if (timelineState.isReady) {
|
|
11758
|
+
return {
|
|
11759
|
+
label: "Ready",
|
|
11760
|
+
className: "bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300 border-green-200 dark:border-green-800"
|
|
11761
|
+
};
|
|
11762
|
+
}
|
|
11763
|
+
if (hasRisk) {
|
|
11764
|
+
return {
|
|
11765
|
+
label: "At risk",
|
|
11766
|
+
className: "bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300 border-red-200 dark:border-red-800"
|
|
11767
|
+
};
|
|
11768
|
+
}
|
|
11769
|
+
switch (timelineState.currentStep) {
|
|
11770
|
+
case "document":
|
|
11771
|
+
return {
|
|
11772
|
+
label: "Pending approval",
|
|
11773
|
+
className: "bg-muted text-muted-foreground border-border"
|
|
11774
|
+
};
|
|
11775
|
+
case "production":
|
|
11776
|
+
return {
|
|
11777
|
+
label: "In production",
|
|
11778
|
+
className: "bg-amber-100 dark:bg-amber-900/50 text-amber-700 dark:text-amber-300 border-amber-200 dark:border-amber-800"
|
|
11779
|
+
};
|
|
11780
|
+
default:
|
|
11781
|
+
return {
|
|
11782
|
+
label: "Not ready",
|
|
11783
|
+
className: "bg-muted text-muted-foreground border-border"
|
|
11784
|
+
};
|
|
11785
|
+
}
|
|
11786
|
+
};
|
|
11787
|
+
const status = getPackingStatus();
|
|
11788
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11789
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Packing status:" }),
|
|
11790
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
11791
|
+
"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border",
|
|
11792
|
+
status.className
|
|
11793
|
+
), children: status.label })
|
|
11794
|
+
] });
|
|
11795
|
+
}
|
|
11796
|
+
function ReadinessMessage({
|
|
11797
|
+
timelineState,
|
|
11798
|
+
hasRisk
|
|
11799
|
+
}) {
|
|
11800
|
+
if (timelineState.isReady && timelineState.deliveryState === "completed") {
|
|
11801
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-green-50/50 dark:bg-green-950/20 border border-green-200 dark:border-green-800/50 p-3", children: [
|
|
11802
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11803
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 text-green-600 dark:text-green-400 shrink-0" }),
|
|
11804
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-green-700 dark:text-green-300", children: "Shipped" })
|
|
11805
|
+
] }),
|
|
11806
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-green-600/80 dark:text-green-400/80 mt-1 ml-6", children: "Delivery has been completed." })
|
|
11807
|
+
] });
|
|
11808
|
+
}
|
|
11809
|
+
if (timelineState.isReady) {
|
|
11810
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-green-50/50 dark:bg-green-950/20 border border-green-200 dark:border-green-800/50 p-3", children: [
|
|
11811
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11812
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 text-green-600 dark:text-green-400 shrink-0" }),
|
|
11813
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-green-700 dark:text-green-300", children: "Ready" })
|
|
11814
|
+
] }),
|
|
11815
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-green-600/80 dark:text-green-400/80 mt-1 ml-6", children: "All prerequisites are complete." })
|
|
11816
|
+
] });
|
|
11817
|
+
}
|
|
11818
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11819
|
+
"rounded-lg p-3 border",
|
|
11820
|
+
hasRisk ? "bg-red-50/50 dark:bg-red-950/20 border-red-200 dark:border-red-800/50" : "bg-muted/50 border-border"
|
|
11821
|
+
), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
11822
|
+
hasRisk ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 text-red-500 shrink-0 mt-0.5" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-4 rounded-full bg-primary/20 border border-primary shrink-0 mt-0.5" }),
|
|
11823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
11824
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
11825
|
+
"text-sm font-medium",
|
|
11826
|
+
hasRisk ? "text-red-700 dark:text-red-300" : "text-foreground"
|
|
11827
|
+
), children: [
|
|
11828
|
+
"Currently in: ",
|
|
11829
|
+
timelineState.currentStepLabel
|
|
11830
|
+
] }),
|
|
11831
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(
|
|
11832
|
+
"text-xs mt-0.5",
|
|
11833
|
+
hasRisk ? "text-red-600/80 dark:text-red-400/80" : "text-muted-foreground"
|
|
11834
|
+
), children: timelineState.reason })
|
|
11835
|
+
] })
|
|
11836
|
+
] }) });
|
|
11837
|
+
}
|
|
9888
11838
|
function getElementRowBg(status) {
|
|
9889
11839
|
switch (status) {
|
|
9890
11840
|
case "loaded":
|
|
@@ -10058,31 +12008,6 @@ function CommentsSection({
|
|
|
10058
12008
|
)
|
|
10059
12009
|
] });
|
|
10060
12010
|
}
|
|
10061
|
-
function getDeliveryHeaderStyles(state, hasRisk) {
|
|
10062
|
-
if (hasRisk) {
|
|
10063
|
-
return {
|
|
10064
|
-
iconBg: "bg-red-100 dark:bg-red-950/50",
|
|
10065
|
-
iconColor: "text-red-600 dark:text-red-400"
|
|
10066
|
-
};
|
|
10067
|
-
}
|
|
10068
|
-
switch (state) {
|
|
10069
|
-
case "sent":
|
|
10070
|
-
return {
|
|
10071
|
-
iconBg: "bg-green-100 dark:bg-green-950/50",
|
|
10072
|
-
iconColor: "text-green-600 dark:text-green-400"
|
|
10073
|
-
};
|
|
10074
|
-
case "ready":
|
|
10075
|
-
return {
|
|
10076
|
-
iconBg: "bg-green-100 dark:bg-green-950/50",
|
|
10077
|
-
iconColor: "text-green-600 dark:text-green-400"
|
|
10078
|
-
};
|
|
10079
|
-
default:
|
|
10080
|
-
return {
|
|
10081
|
-
iconBg: "bg-muted",
|
|
10082
|
-
iconColor: "text-muted-foreground"
|
|
10083
|
-
};
|
|
10084
|
-
}
|
|
10085
|
-
}
|
|
10086
12011
|
function DeliveryDetailPage({
|
|
10087
12012
|
delivery,
|
|
10088
12013
|
week,
|
|
@@ -10093,13 +12018,7 @@ function DeliveryDetailPage({
|
|
|
10093
12018
|
onAddComment,
|
|
10094
12019
|
onConfirmLoad
|
|
10095
12020
|
}) {
|
|
10096
|
-
const
|
|
10097
|
-
const headerStyles = getDeliveryHeaderStyles(visualState, delivery.hasProductionRisk ?? false);
|
|
10098
|
-
const loadedCount = delivery.loadedCount ?? delivery.elements.filter((e) => e.status === "loaded").length;
|
|
10099
|
-
const totalCount = delivery.totalCount ?? delivery.elements.length;
|
|
10100
|
-
const loadedPercent = totalCount > 0 ? Math.round(loadedCount / totalCount * 100) : 0;
|
|
10101
|
-
const producedCount = delivery.producedCount ?? loadedCount;
|
|
10102
|
-
const producedPercent = totalCount > 0 ? Math.round(producedCount / totalCount * 100) : 0;
|
|
12021
|
+
const timelineState = getTimelineState(delivery);
|
|
10103
12022
|
const elementsByStatus = React27__namespace.useMemo(() => {
|
|
10104
12023
|
const loaded = delivery.elements.filter((e) => e.status === "loaded");
|
|
10105
12024
|
const missing = delivery.elements.filter((e) => e.status === "missing");
|
|
@@ -10108,6 +12027,7 @@ function DeliveryDetailPage({
|
|
|
10108
12027
|
return { loaded, missing, moved, addons };
|
|
10109
12028
|
}, [delivery.elements]);
|
|
10110
12029
|
const preLoadingComments = delivery.comments.filter((c) => c.context === "pre_unloading");
|
|
12030
|
+
const projectName = delivery.destination || delivery.label;
|
|
10111
12031
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
10112
12032
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-4 py-3 border-b bg-background sticky top-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10113
12033
|
Button,
|
|
@@ -10123,129 +12043,39 @@ function DeliveryDetailPage({
|
|
|
10123
12043
|
}
|
|
10124
12044
|
) }),
|
|
10125
12045
|
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pb-6 space-y-6", children: [
|
|
10126
|
-
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pt-4 space-y-
|
|
12046
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pt-4 space-y-3", children: [
|
|
10127
12047
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
10128
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10129
|
-
|
|
10130
|
-
"flex items-center justify-center h-12 w-12 rounded-xl shrink-0",
|
|
10131
|
-
headerStyles.iconBg
|
|
10132
|
-
), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-6 w-6", headerStyles.iconColor) }) }),
|
|
10133
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10134
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10135
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold", children: delivery.label }),
|
|
10136
|
-
visualState === "sent" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-5 w-5 text-green-600 dark:text-green-400" }),
|
|
10137
|
-
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-5 w-5 text-red-500" })
|
|
10138
|
-
] }),
|
|
10139
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
10140
|
-
delivery.supplierName,
|
|
10141
|
-
delivery.prefixScope && ` \u2022 ${delivery.prefixScope}`
|
|
10142
|
-
] })
|
|
10143
|
-
] })
|
|
10144
|
-
] }),
|
|
10145
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end gap-1.5", children: [
|
|
10146
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10147
|
-
Badge,
|
|
10148
|
-
{
|
|
10149
|
-
variant: getStatusBadgeVariant2(delivery.status),
|
|
10150
|
-
className: cn("shrink-0", getStatusBadgeClasses2(delivery.status)),
|
|
10151
|
-
children: getLoadingDeliveryStatusLabel(delivery.status)
|
|
10152
|
-
}
|
|
10153
|
-
),
|
|
10154
|
-
delivery.isReadyToUnload && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10155
|
-
Badge,
|
|
10156
|
-
{
|
|
10157
|
-
variant: "outline",
|
|
10158
|
-
className: "bg-green-100 dark:bg-green-900/50 border-green-300 dark:border-green-700 text-green-700 dark:text-green-300",
|
|
10159
|
-
children: "Ready to load"
|
|
10160
|
-
}
|
|
10161
|
-
)
|
|
10162
|
-
] })
|
|
12048
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold leading-tight line-clamp-2", children: projectName }),
|
|
12049
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-5 w-5 text-red-500 shrink-0 mt-0.5" })
|
|
10163
12050
|
] }),
|
|
10164
|
-
|
|
10165
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
10166
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
10167
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
12051
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground", children: [
|
|
12052
|
+
delivery.location && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
12053
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
12054
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: delivery.location })
|
|
10168
12055
|
] }),
|
|
10169
|
-
delivery.riskReason && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600 dark:text-red-400 mt-1 ml-6", children: delivery.riskReason })
|
|
10170
|
-
] }),
|
|
10171
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-4 text-sm text-muted-foreground", children: [
|
|
10172
12056
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
10173
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-
|
|
10174
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-4 w-4" }),
|
|
10182
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: delivery.destination })
|
|
10183
|
-
] })
|
|
10184
|
-
] }),
|
|
10185
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-4 space-y-3", children: [
|
|
10186
|
-
(delivery.producedCount !== void 0 || delivery.producedTons !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
10187
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
10188
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Production" }),
|
|
10189
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
10190
|
-
"text-sm font-semibold tabular-nums",
|
|
10191
|
-
delivery.isReadyToUnload ? "text-green-600 dark:text-green-400" : delivery.hasProductionRisk ? "text-red-600 dark:text-red-400" : ""
|
|
10192
|
-
), children: [
|
|
10193
|
-
delivery.producedTons !== void 0 && delivery.totalTons !== void 0 ? `${delivery.producedTons} / ${delivery.totalTons} tons` : `Produced ${producedCount} / ${totalCount}`,
|
|
10194
|
-
delivery.isReadyToUnload && " \u2713"
|
|
10195
|
-
] })
|
|
10196
|
-
] }),
|
|
10197
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10198
|
-
"div",
|
|
10199
|
-
{
|
|
10200
|
-
className: cn(
|
|
10201
|
-
"h-full rounded-full transition-all",
|
|
10202
|
-
delivery.isReadyToUnload ? "bg-green-500" : delivery.hasProductionRisk ? "bg-red-500" : "bg-amber-500"
|
|
10203
|
-
),
|
|
10204
|
-
style: { width: `${producedPercent}%` }
|
|
10205
|
-
}
|
|
10206
|
-
) })
|
|
10207
|
-
] }),
|
|
10208
|
-
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
10209
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
10210
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
10211
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Loading Progress" }),
|
|
10212
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold tabular-nums", children: [
|
|
10213
|
-
"Loaded ",
|
|
10214
|
-
loadedCount,
|
|
10215
|
-
" / ",
|
|
10216
|
-
totalCount
|
|
10217
|
-
] })
|
|
10218
|
-
] }),
|
|
10219
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10220
|
-
"div",
|
|
10221
|
-
{
|
|
10222
|
-
className: cn(
|
|
10223
|
-
"h-full rounded-full transition-all",
|
|
10224
|
-
loadedPercent === 100 ? "bg-green-500" : "bg-primary"
|
|
10225
|
-
),
|
|
10226
|
-
style: { width: `${loadedPercent}%` }
|
|
10227
|
-
}
|
|
10228
|
-
) }),
|
|
10229
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap text-xs", children: [
|
|
10230
|
-
elementsByStatus.loaded.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-green-600 dark:text-green-400", children: [
|
|
10231
|
-
elementsByStatus.loaded.length,
|
|
10232
|
-
" Loaded"
|
|
10233
|
-
] }),
|
|
10234
|
-
elementsByStatus.missing.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
10235
|
-
elementsByStatus.missing.length,
|
|
10236
|
-
" Missing"
|
|
10237
|
-
] }),
|
|
10238
|
-
elementsByStatus.moved.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-blue-600 dark:text-blue-400", children: [
|
|
10239
|
-
elementsByStatus.moved.length,
|
|
10240
|
-
" Moved"
|
|
10241
|
-
] }),
|
|
10242
|
-
elementsByStatus.addons.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-600 dark:text-purple-400", children: [
|
|
10243
|
-
elementsByStatus.addons.length,
|
|
10244
|
-
" Add-on"
|
|
10245
|
-
] })
|
|
12057
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
12058
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
12059
|
+
"Expected on site: ",
|
|
12060
|
+
delivery.date.toLocaleDateString("en-US", {
|
|
12061
|
+
day: "numeric",
|
|
12062
|
+
month: "short",
|
|
12063
|
+
year: "numeric"
|
|
12064
|
+
})
|
|
10246
12065
|
] })
|
|
10247
12066
|
] })
|
|
10248
|
-
] })
|
|
12067
|
+
] }),
|
|
12068
|
+
/* @__PURE__ */ jsxRuntime.jsx(PackingStatusBadge, { timelineState, hasRisk: delivery.hasProductionRisk ?? false })
|
|
12069
|
+
] }),
|
|
12070
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
12071
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: /* @__PURE__ */ jsxRuntime.jsx(DeliveryTimeline, { timelineState }) }),
|
|
12072
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12073
|
+
ReadinessMessage,
|
|
12074
|
+
{
|
|
12075
|
+
timelineState,
|
|
12076
|
+
hasRisk: delivery.hasProductionRisk ?? false
|
|
12077
|
+
}
|
|
12078
|
+
)
|
|
10249
12079
|
] }),
|
|
10250
12080
|
(elementsByStatus.loaded.length > 0 || elementsByStatus.missing.length > 0 || elementsByStatus.moved.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
10251
12081
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -10423,31 +12253,74 @@ function SupplierWeeklyLoading({
|
|
|
10423
12253
|
handleCommentSubmit();
|
|
10424
12254
|
}
|
|
10425
12255
|
};
|
|
12256
|
+
const insightMetrics = React27__namespace.useMemo(() => {
|
|
12257
|
+
const totalDeliveries = deliveries.length;
|
|
12258
|
+
const readyDeliveries = deliveries.filter((d) => d.isReadyToUnload).length;
|
|
12259
|
+
deliveries.filter(
|
|
12260
|
+
(d) => d.status === "shipped" || d.status === "delivered"
|
|
12261
|
+
).length;
|
|
12262
|
+
const totalTonsRequired = deliveries.reduce((sum, d) => sum + (d.totalTons ?? 0), 0);
|
|
12263
|
+
const producedTons = deliveries.reduce((sum, d) => sum + (d.producedTons ?? 0), 0);
|
|
12264
|
+
return [
|
|
12265
|
+
{
|
|
12266
|
+
key: "deliveries",
|
|
12267
|
+
label: "deliveries",
|
|
12268
|
+
value: totalDeliveries,
|
|
12269
|
+
icon: "truck",
|
|
12270
|
+
status: "normal"
|
|
12271
|
+
},
|
|
12272
|
+
{
|
|
12273
|
+
key: "ready",
|
|
12274
|
+
label: "ready",
|
|
12275
|
+
value: readyDeliveries,
|
|
12276
|
+
icon: "check",
|
|
12277
|
+
status: readyDeliveries > 0 ? "success" : "normal"
|
|
12278
|
+
},
|
|
12279
|
+
{
|
|
12280
|
+
key: "required",
|
|
12281
|
+
label: "tons required",
|
|
12282
|
+
value: totalTonsRequired,
|
|
12283
|
+
unit: "t",
|
|
12284
|
+
icon: "factory",
|
|
12285
|
+
status: "normal"
|
|
12286
|
+
},
|
|
12287
|
+
{
|
|
12288
|
+
key: "produced",
|
|
12289
|
+
label: "tons produced",
|
|
12290
|
+
value: producedTons,
|
|
12291
|
+
unit: "t",
|
|
12292
|
+
icon: "factory",
|
|
12293
|
+
status: producedTons >= totalTonsRequired ? "success" : producedTons >= totalTonsRequired * 0.5 ? "normal" : "warning"
|
|
12294
|
+
}
|
|
12295
|
+
];
|
|
12296
|
+
}, [deliveries]);
|
|
10426
12297
|
const Wrapper = bordered ? Card : "div";
|
|
10427
12298
|
const Content14 = bordered ? CardContent : "div";
|
|
10428
12299
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10429
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10430
|
-
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
|
|
10446
|
-
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
|
|
10450
|
-
|
|
12300
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-0", className), children: [
|
|
12301
|
+
/* @__PURE__ */ jsxRuntime.jsx(InsightBar, { metrics: insightMetrics, className: "rounded-t-lg border border-b-0" }),
|
|
12302
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12303
|
+
Wrapper,
|
|
12304
|
+
{
|
|
12305
|
+
className: cn(
|
|
12306
|
+
"flex flex-col overflow-hidden rounded-t-none",
|
|
12307
|
+
// Removed fixed min-height - content-driven sizing
|
|
12308
|
+
!bordered && "border border-border bg-card rounded-lg rounded-t-none"
|
|
12309
|
+
),
|
|
12310
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Content14, { className: cn("flex-1 overflow-hidden p-0", !bordered && ""), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12311
|
+
WeeklyLoadingView,
|
|
12312
|
+
{
|
|
12313
|
+
week,
|
|
12314
|
+
deliveries,
|
|
12315
|
+
onDeliveryClick: handleDeliveryClick,
|
|
12316
|
+
onDeliveryCommentClick: handleDeliveryCommentClick,
|
|
12317
|
+
onWeekChange,
|
|
12318
|
+
showNavigation
|
|
12319
|
+
}
|
|
12320
|
+
) })
|
|
12321
|
+
}
|
|
12322
|
+
)
|
|
12323
|
+
] }),
|
|
10451
12324
|
/* @__PURE__ */ jsxRuntime.jsx(Sheet, { open: sheetOpen, onOpenChange: (open) => !open && handleSheetClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10452
12325
|
SheetContent,
|
|
10453
12326
|
{
|
|
@@ -10524,59 +12397,40 @@ function SupplierWeeklyLoading({
|
|
|
10524
12397
|
] }) })
|
|
10525
12398
|
] });
|
|
10526
12399
|
}
|
|
10527
|
-
function
|
|
10528
|
-
switch (status) {
|
|
10529
|
-
case "shipped":
|
|
10530
|
-
case "delivered":
|
|
10531
|
-
return "default";
|
|
10532
|
-
case "loaded":
|
|
10533
|
-
case "in_progress":
|
|
10534
|
-
return "secondary";
|
|
10535
|
-
case "cancelled":
|
|
10536
|
-
return "destructive";
|
|
10537
|
-
case "planned":
|
|
10538
|
-
default:
|
|
10539
|
-
return "outline";
|
|
10540
|
-
}
|
|
10541
|
-
}
|
|
10542
|
-
function getStatusBadgeClasses3(status) {
|
|
10543
|
-
switch (status) {
|
|
10544
|
-
case "shipped":
|
|
10545
|
-
case "delivered":
|
|
10546
|
-
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
10547
|
-
case "loaded":
|
|
10548
|
-
return "border-blue-500 text-blue-600 bg-blue-50 dark:bg-blue-950/50";
|
|
10549
|
-
case "in_progress":
|
|
10550
|
-
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
10551
|
-
case "cancelled":
|
|
10552
|
-
return "";
|
|
10553
|
-
case "planned":
|
|
10554
|
-
default:
|
|
10555
|
-
return "border-muted-foreground/50 text-muted-foreground";
|
|
10556
|
-
}
|
|
10557
|
-
}
|
|
10558
|
-
function getLeftStrokeStyles2(state, hasRisk, isHovered) {
|
|
12400
|
+
function getCardStyles2(state, hasRisk) {
|
|
10559
12401
|
if (hasRisk) {
|
|
10560
12402
|
return {
|
|
10561
|
-
|
|
10562
|
-
|
|
12403
|
+
fill: statusCellFillClasses.risk.combined,
|
|
12404
|
+
titleColor: statusCellTextClasses.risk.title,
|
|
12405
|
+
subtitleColor: statusCellTextClasses.risk.subtitle,
|
|
12406
|
+
iconColor: statusCellTextClasses.risk.icon,
|
|
12407
|
+
opacity: ""
|
|
10563
12408
|
};
|
|
10564
12409
|
}
|
|
10565
12410
|
switch (state) {
|
|
10566
12411
|
case "sent":
|
|
10567
12412
|
return {
|
|
10568
|
-
|
|
10569
|
-
|
|
12413
|
+
fill: statusCellFillClasses.shipped.combined,
|
|
12414
|
+
titleColor: statusCellTextClasses.shipped.title,
|
|
12415
|
+
subtitleColor: statusCellTextClasses.shipped.subtitle,
|
|
12416
|
+
iconColor: statusCellTextClasses.shipped.icon,
|
|
12417
|
+
opacity: "opacity-75"
|
|
10570
12418
|
};
|
|
10571
12419
|
case "ready":
|
|
10572
12420
|
return {
|
|
10573
|
-
|
|
10574
|
-
|
|
12421
|
+
fill: statusCellFillClasses.ready.combined,
|
|
12422
|
+
titleColor: statusCellTextClasses.ready.title,
|
|
12423
|
+
subtitleColor: statusCellTextClasses.ready.subtitle,
|
|
12424
|
+
iconColor: statusCellTextClasses.ready.icon,
|
|
12425
|
+
opacity: ""
|
|
10575
12426
|
};
|
|
10576
12427
|
default:
|
|
10577
12428
|
return {
|
|
10578
|
-
|
|
10579
|
-
|
|
12429
|
+
fill: statusCellFillClasses.normal.combined,
|
|
12430
|
+
titleColor: statusCellTextClasses.normal.title,
|
|
12431
|
+
subtitleColor: statusCellTextClasses.normal.subtitle,
|
|
12432
|
+
iconColor: statusCellTextClasses.normal.icon,
|
|
12433
|
+
opacity: ""
|
|
10580
12434
|
};
|
|
10581
12435
|
}
|
|
10582
12436
|
}
|
|
@@ -10585,22 +12439,10 @@ function DeliveryCard({
|
|
|
10585
12439
|
onTap,
|
|
10586
12440
|
className
|
|
10587
12441
|
}) {
|
|
10588
|
-
const [isHovered, setIsHovered] = React27__namespace.useState(false);
|
|
10589
12442
|
const hasComments = delivery.comments.length > 0;
|
|
10590
12443
|
const visualState = getDeliveryVisualState(delivery);
|
|
10591
|
-
const styles =
|
|
10592
|
-
const
|
|
10593
|
-
if (delivery.producedTons !== void 0 && delivery.totalTons !== void 0) {
|
|
10594
|
-
return `${delivery.producedTons} / ${delivery.totalTons}t produced`;
|
|
10595
|
-
}
|
|
10596
|
-
if (delivery.producedCount !== void 0 && delivery.totalCount !== void 0) {
|
|
10597
|
-
return `${delivery.producedCount} / ${delivery.totalCount} produced`;
|
|
10598
|
-
}
|
|
10599
|
-
if (delivery.loadedCount !== void 0 && delivery.totalCount !== void 0) {
|
|
10600
|
-
return `Loaded ${delivery.loadedCount} / ${delivery.totalCount}`;
|
|
10601
|
-
}
|
|
10602
|
-
return null;
|
|
10603
|
-
}, [delivery]);
|
|
12444
|
+
const styles = getCardStyles2(visualState, delivery.hasProductionRisk ?? false);
|
|
12445
|
+
const projectName = delivery.destination || delivery.label;
|
|
10604
12446
|
const handleClick = () => {
|
|
10605
12447
|
onTap?.();
|
|
10606
12448
|
};
|
|
@@ -10617,76 +12459,47 @@ function DeliveryCard({
|
|
|
10617
12459
|
tabIndex: 0,
|
|
10618
12460
|
onClick: handleClick,
|
|
10619
12461
|
onKeyDown: handleKeyDown,
|
|
10620
|
-
onMouseEnter: () => setIsHovered(true),
|
|
10621
|
-
onMouseLeave: () => setIsHovered(false),
|
|
10622
12462
|
className: cn(
|
|
10623
|
-
// Full-width,
|
|
10624
|
-
"w-full rounded-
|
|
12463
|
+
// Full-width, small radius (matching planning table cards)
|
|
12464
|
+
"w-full rounded-lg",
|
|
10625
12465
|
// Touch-friendly sizing - 56px min-height for iPad
|
|
10626
12466
|
"min-h-[56px] p-4",
|
|
10627
|
-
//
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
12467
|
+
// FULL-CARD STATUS FILL - uses shared calibration/planning tokens
|
|
12468
|
+
// This is the key change: status fill on outermost container
|
|
12469
|
+
styles.fill,
|
|
12470
|
+
// Opacity for shipped state
|
|
12471
|
+
styles.opacity,
|
|
12472
|
+
// Hover/tap state - lift effect (disabled for shipped)
|
|
10632
12473
|
"cursor-pointer transition-all duration-200 ease-out",
|
|
10633
|
-
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
12474
|
+
visualState !== "sent" && "hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
10634
12475
|
"active:translate-y-0 active:shadow-sm",
|
|
10635
12476
|
// Focus state
|
|
10636
12477
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
10637
|
-
// Greyed out for sent state
|
|
10638
|
-
visualState === "sent" && "opacity-60",
|
|
10639
12478
|
className
|
|
10640
12479
|
),
|
|
10641
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
10642
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
10643
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
|
|
10647
|
-
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
|
|
10652
|
-
{
|
|
10653
|
-
variant: "outline",
|
|
10654
|
-
className: "text-[9px] px-1.5 py-0 h-4 bg-green-100 dark:bg-green-900/50 border-green-300 dark:border-green-700 text-green-700 dark:text-green-300",
|
|
10655
|
-
children: "Ready"
|
|
10656
|
-
}
|
|
10657
|
-
),
|
|
10658
|
-
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 text-red-500 shrink-0" }),
|
|
10659
|
-
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
|
|
10660
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
10661
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-primary" })
|
|
10662
|
-
] })
|
|
10663
|
-
] }),
|
|
10664
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground truncate", children: [
|
|
10665
|
-
delivery.supplierName,
|
|
10666
|
-
delivery.prefixScope && ` \u2022 ${delivery.prefixScope}`
|
|
10667
|
-
] }),
|
|
10668
|
-
productionDisplay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
10669
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-3 w-3 text-muted-foreground" }),
|
|
10670
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
10671
|
-
delivery.isReadyToUnload ? "text-green-600 dark:text-green-400 font-medium" : delivery.hasProductionRisk ? "text-red-600 dark:text-red-400" : "text-muted-foreground"
|
|
10672
|
-
), children: [
|
|
10673
|
-
delivery.isReadyToUnload ? "\u2713 " : "",
|
|
10674
|
-
productionDisplay
|
|
10675
|
-
] })
|
|
12480
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
12481
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0 flex-1", children: [
|
|
12482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
12483
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
12484
|
+
"text-sm font-semibold truncate",
|
|
12485
|
+
styles.titleColor
|
|
12486
|
+
), children: projectName }),
|
|
12487
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: cn("h-4 w-4 shrink-0", styles.iconColor) }),
|
|
12488
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0 p-0.5 rounded bg-background/50", children: [
|
|
12489
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
12490
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-primary" })
|
|
10676
12491
|
] })
|
|
12492
|
+
] }),
|
|
12493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
12494
|
+
visualState === "sent" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12495
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-3.5 w-3.5 shrink-0", styles.iconColor) }),
|
|
12496
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-medium uppercase tracking-wide", styles.subtitleColor), children: "Shipped" })
|
|
12497
|
+
] }),
|
|
12498
|
+
visualState === "ready" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-semibold uppercase tracking-wide", styles.subtitleColor), children: "Ready" }),
|
|
12499
|
+
delivery.hasProductionRisk && visualState !== "sent" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-semibold uppercase tracking-wide", styles.subtitleColor), children: "At Risk" })
|
|
10677
12500
|
] })
|
|
10678
12501
|
] }),
|
|
10679
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10680
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10681
|
-
Badge,
|
|
10682
|
-
{
|
|
10683
|
-
variant: getStatusBadgeVariant3(delivery.status),
|
|
10684
|
-
className: cn("text-[10px] h-5", getStatusBadgeClasses3(delivery.status)),
|
|
10685
|
-
children: getLoadingDeliveryStatusLabel(delivery.status)
|
|
10686
|
-
}
|
|
10687
|
-
),
|
|
10688
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
10689
|
-
] })
|
|
12502
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: cn("h-4 w-4 shrink-0", styles.iconColor) })
|
|
10690
12503
|
] })
|
|
10691
12504
|
}
|
|
10692
12505
|
);
|
|
@@ -13911,7 +15724,7 @@ var GanttContentHeader = ({
|
|
|
13911
15724
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13912
15725
|
"div",
|
|
13913
15726
|
{
|
|
13914
|
-
className: "sticky top-0 z-20 grid w-full shrink-0 bg-
|
|
15727
|
+
className: "sticky top-0 z-20 grid w-full shrink-0 bg-muted/80 backdrop-blur-sm",
|
|
13915
15728
|
style: { height: "var(--gantt-header-height)" },
|
|
13916
15729
|
children: [
|
|
13917
15730
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -14108,7 +15921,7 @@ var GanttSidebarHeader = ({
|
|
|
14108
15921
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14109
15922
|
"div",
|
|
14110
15923
|
{
|
|
14111
|
-
className: "sticky top-0 z-
|
|
15924
|
+
className: "sticky top-0 z-40 flex shrink-0 items-end justify-between gap-2.5 border-border/50 border-b bg-muted/80 px-2.5 py-2 font-medium text-muted-foreground text-xs backdrop-blur-sm",
|
|
14112
15925
|
style: { height: "var(--gantt-header-height)" },
|
|
14113
15926
|
children: [
|
|
14114
15927
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex-1 truncate text-left", children: title }),
|
|
@@ -14172,11 +15985,12 @@ var GanttGroupSummaryBar = React27.memo(({
|
|
|
14172
15985
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14173
15986
|
"div",
|
|
14174
15987
|
{
|
|
14175
|
-
className: "h-full w-full rounded-sm border border-border/60 bg-muted/40 shadow-sm",
|
|
15988
|
+
className: "relative h-full w-full rounded-sm border border-border/60 bg-muted/40 shadow-sm overflow-hidden",
|
|
14176
15989
|
style: {
|
|
14177
15990
|
// Subtle gradient for depth
|
|
14178
15991
|
background: "linear-gradient(180deg, hsl(var(--muted) / 0.5) 0%, hsl(var(--muted) / 0.3) 100%)"
|
|
14179
|
-
}
|
|
15992
|
+
},
|
|
15993
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[10px] font-medium text-muted-foreground", children: group.title }) })
|
|
14180
15994
|
}
|
|
14181
15995
|
)
|
|
14182
15996
|
}
|
|
@@ -14208,7 +16022,7 @@ var GanttCollapsibleSidebarGroup = ({
|
|
|
14208
16022
|
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14209
16023
|
"button",
|
|
14210
16024
|
{
|
|
14211
|
-
className: "flex w-full items-center gap-2 px-2.5 py-2 text-left font-medium text-xs hover:bg-muted/
|
|
16025
|
+
className: "flex w-full items-center gap-2 px-2.5 py-2 text-left font-medium text-xs hover:bg-muted/70 border-b border-border/50 bg-muted/40",
|
|
14212
16026
|
style: { height: "var(--gantt-row-height)" },
|
|
14213
16027
|
type: "button",
|
|
14214
16028
|
children: [
|
|
@@ -14250,7 +16064,7 @@ var GanttCollapsibleTimelineGroup = ({
|
|
|
14250
16064
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14251
16065
|
"div",
|
|
14252
16066
|
{
|
|
14253
|
-
className: "relative w-full border-b border-border/50",
|
|
16067
|
+
className: "relative w-full border-b border-border/50 bg-muted/20",
|
|
14254
16068
|
style: { height: "var(--gantt-row-height)" },
|
|
14255
16069
|
children: /* @__PURE__ */ jsxRuntime.jsx(GanttGroupSummaryBar, { group })
|
|
14256
16070
|
}
|
|
@@ -14268,7 +16082,7 @@ var GanttSidebarGroup = ({
|
|
|
14268
16082
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14269
16083
|
"p",
|
|
14270
16084
|
{
|
|
14271
|
-
className: "w-full truncate px-2.5 py-2 text-left font-medium text-muted-foreground text-xs border-b border-border/50 bg-
|
|
16085
|
+
className: "w-full truncate px-2.5 py-2 text-left font-medium text-muted-foreground text-xs border-b border-border/50 bg-muted/40",
|
|
14272
16086
|
style: { height: "var(--gantt-row-height)" },
|
|
14273
16087
|
children: name
|
|
14274
16088
|
}
|
|
@@ -14282,7 +16096,7 @@ var GanttSidebar = ({
|
|
|
14282
16096
|
"div",
|
|
14283
16097
|
{
|
|
14284
16098
|
className: cn(
|
|
14285
|
-
"sticky left-0 z-30 h-max min-h-full border-border/50 border-r bg-
|
|
16099
|
+
"sticky left-0 z-30 h-max min-h-full border-border/50 border-r bg-muted/50",
|
|
14286
16100
|
className
|
|
14287
16101
|
),
|
|
14288
16102
|
style: { width: "var(--gantt-sidebar-width)" },
|
|
@@ -15446,6 +17260,8 @@ exports.CircularProgress = CircularProgress;
|
|
|
15446
17260
|
exports.Collapsible = Collapsible;
|
|
15447
17261
|
exports.CollapsibleContent = CollapsibleContent2;
|
|
15448
17262
|
exports.CollapsibleTrigger = CollapsibleTrigger2;
|
|
17263
|
+
exports.ColumnSummaryCell = ColumnSummaryCell;
|
|
17264
|
+
exports.ColumnSummaryStrip = ColumnSummaryStrip;
|
|
15449
17265
|
exports.Command = Command;
|
|
15450
17266
|
exports.CommandDialog = CommandDialog;
|
|
15451
17267
|
exports.CommandEmpty = CommandEmpty;
|
|
@@ -15585,6 +17401,7 @@ exports.InputGroupButton = InputGroupButton;
|
|
|
15585
17401
|
exports.InputGroupInput = InputGroupInput;
|
|
15586
17402
|
exports.InputGroupText = InputGroupText;
|
|
15587
17403
|
exports.InputGroupTextarea = InputGroupTextarea;
|
|
17404
|
+
exports.InsightBar = InsightBar;
|
|
15588
17405
|
exports.Item = Item6;
|
|
15589
17406
|
exports.ItemActions = ItemActions;
|
|
15590
17407
|
exports.ItemContent = ItemContent;
|
|
@@ -15732,6 +17549,7 @@ exports.SiteHeader = SiteHeader;
|
|
|
15732
17549
|
exports.Skeleton = Skeleton;
|
|
15733
17550
|
exports.Slider = Slider;
|
|
15734
17551
|
exports.Spinner = Spinner;
|
|
17552
|
+
exports.StatusProgress = StatusProgress;
|
|
15735
17553
|
exports.SubmitCalibrationBar = SubmitCalibrationBar;
|
|
15736
17554
|
exports.SupplierCell = SupplierCell;
|
|
15737
17555
|
exports.SupplierWeeklyLoading = SupplierWeeklyLoading;
|
|
@@ -15767,6 +17585,7 @@ exports.UserAvatarsDropdown = UserAvatarsDropdown;
|
|
|
15767
17585
|
exports.VIEW_LABELS = VIEW_LABELS;
|
|
15768
17586
|
exports.WeekCell = WeekCell;
|
|
15769
17587
|
exports.WeekDetailDialog = WeekDetailDialog;
|
|
17588
|
+
exports.WeekDetailSheet = WeekDetailSheet;
|
|
15770
17589
|
exports.WeekHeader = WeekHeader;
|
|
15771
17590
|
exports.WeekView = WeekView;
|
|
15772
17591
|
exports.WeeklyLoadingView = WeeklyLoadingView;
|