@j3m-quantum/ui 1.11.2 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2018 -790
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -29
- package/dist/index.d.ts +110 -29
- package/dist/index.js +1946 -720
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React29 = require('react');
|
|
4
4
|
var reactSlot = require('@radix-ui/react-slot');
|
|
5
5
|
var classVarianceAuthority = require('class-variance-authority');
|
|
6
6
|
var clsx = require('clsx');
|
|
@@ -73,7 +73,7 @@ function _interopNamespace(e) {
|
|
|
73
73
|
return Object.freeze(n);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
var
|
|
76
|
+
var React29__namespace = /*#__PURE__*/_interopNamespace(React29);
|
|
77
77
|
var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
|
|
78
78
|
var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
|
|
79
79
|
var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
|
|
@@ -108,8 +108,8 @@ var tunnel__default = /*#__PURE__*/_interopDefault(tunnel);
|
|
|
108
108
|
// src/hooks/use-mobile.ts
|
|
109
109
|
var MOBILE_BREAKPOINT = 768;
|
|
110
110
|
function useIsMobile() {
|
|
111
|
-
const [isMobile, setIsMobile] =
|
|
112
|
-
|
|
111
|
+
const [isMobile, setIsMobile] = React29__namespace.useState(void 0);
|
|
112
|
+
React29__namespace.useEffect(() => {
|
|
113
113
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
114
114
|
const onChange = () => {
|
|
115
115
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -150,7 +150,7 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
);
|
|
153
|
-
var Button =
|
|
153
|
+
var Button = React29__namespace.forwardRef(
|
|
154
154
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
155
155
|
const Comp = asChild ? reactSlot.Slot : "button";
|
|
156
156
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -514,7 +514,7 @@ function Slider({
|
|
|
514
514
|
max = 100,
|
|
515
515
|
...props
|
|
516
516
|
}) {
|
|
517
|
-
const _values =
|
|
517
|
+
const _values = React29__namespace.useMemo(
|
|
518
518
|
() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
|
|
519
519
|
[value, defaultValue, min, max]
|
|
520
520
|
);
|
|
@@ -800,7 +800,7 @@ function Toggle({
|
|
|
800
800
|
}
|
|
801
801
|
);
|
|
802
802
|
}
|
|
803
|
-
var ToggleGroupContext =
|
|
803
|
+
var ToggleGroupContext = React29__namespace.createContext({
|
|
804
804
|
size: "default",
|
|
805
805
|
variant: "default",
|
|
806
806
|
spacing: 0
|
|
@@ -837,7 +837,7 @@ function ToggleGroupItem({
|
|
|
837
837
|
size,
|
|
838
838
|
...props
|
|
839
839
|
}) {
|
|
840
|
-
const context =
|
|
840
|
+
const context = React29__namespace.useContext(ToggleGroupContext);
|
|
841
841
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
842
842
|
ToggleGroupPrimitive__namespace.Item,
|
|
843
843
|
{
|
|
@@ -867,7 +867,7 @@ function ThemeSwitch({
|
|
|
867
867
|
className,
|
|
868
868
|
size = "default"
|
|
869
869
|
}) {
|
|
870
|
-
const [isChecked, setIsChecked] =
|
|
870
|
+
const [isChecked, setIsChecked] = React29__namespace.useState(defaultChecked);
|
|
871
871
|
const isControlled = checked !== void 0;
|
|
872
872
|
const currentChecked = isControlled ? checked : isChecked;
|
|
873
873
|
const handleClick = () => {
|
|
@@ -1287,7 +1287,7 @@ function Label2({
|
|
|
1287
1287
|
);
|
|
1288
1288
|
}
|
|
1289
1289
|
var Form = reactHookForm.FormProvider;
|
|
1290
|
-
var FormFieldContext =
|
|
1290
|
+
var FormFieldContext = React29__namespace.createContext(
|
|
1291
1291
|
{}
|
|
1292
1292
|
);
|
|
1293
1293
|
var FormField = ({
|
|
@@ -1296,8 +1296,8 @@ var FormField = ({
|
|
|
1296
1296
|
return /* @__PURE__ */ jsxRuntime.jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.Controller, { ...props }) });
|
|
1297
1297
|
};
|
|
1298
1298
|
var useFormField = () => {
|
|
1299
|
-
const fieldContext =
|
|
1300
|
-
const itemContext =
|
|
1299
|
+
const fieldContext = React29__namespace.useContext(FormFieldContext);
|
|
1300
|
+
const itemContext = React29__namespace.useContext(FormItemContext);
|
|
1301
1301
|
const { getFieldState } = reactHookForm.useFormContext();
|
|
1302
1302
|
const formState = reactHookForm.useFormState({ name: fieldContext.name });
|
|
1303
1303
|
const fieldState = getFieldState(fieldContext.name, formState);
|
|
@@ -1314,11 +1314,11 @@ var useFormField = () => {
|
|
|
1314
1314
|
...fieldState
|
|
1315
1315
|
};
|
|
1316
1316
|
};
|
|
1317
|
-
var FormItemContext =
|
|
1317
|
+
var FormItemContext = React29__namespace.createContext(
|
|
1318
1318
|
{}
|
|
1319
1319
|
);
|
|
1320
1320
|
function FormItem({ className, ...props }) {
|
|
1321
|
-
const id =
|
|
1321
|
+
const id = React29__namespace.useId();
|
|
1322
1322
|
return /* @__PURE__ */ jsxRuntime.jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1323
1323
|
"div",
|
|
1324
1324
|
{
|
|
@@ -1566,7 +1566,7 @@ function FieldError({
|
|
|
1566
1566
|
errors,
|
|
1567
1567
|
...props
|
|
1568
1568
|
}) {
|
|
1569
|
-
const content =
|
|
1569
|
+
const content = React29.useMemo(() => {
|
|
1570
1570
|
if (children) {
|
|
1571
1571
|
return children;
|
|
1572
1572
|
}
|
|
@@ -2420,8 +2420,8 @@ function CalendarDayButton({
|
|
|
2420
2420
|
modifiers,
|
|
2421
2421
|
...props
|
|
2422
2422
|
}) {
|
|
2423
|
-
const ref =
|
|
2424
|
-
|
|
2423
|
+
const ref = React29__namespace.useRef(null);
|
|
2424
|
+
React29__namespace.useEffect(() => {
|
|
2425
2425
|
if (modifiers.focused) ref.current?.focus();
|
|
2426
2426
|
}, [modifiers.focused]);
|
|
2427
2427
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2442,9 +2442,9 @@ function CalendarDayButton({
|
|
|
2442
2442
|
}
|
|
2443
2443
|
);
|
|
2444
2444
|
}
|
|
2445
|
-
var CarouselContext =
|
|
2445
|
+
var CarouselContext = React29__namespace.createContext(null);
|
|
2446
2446
|
function useCarousel() {
|
|
2447
|
-
const context =
|
|
2447
|
+
const context = React29__namespace.useContext(CarouselContext);
|
|
2448
2448
|
if (!context) {
|
|
2449
2449
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
2450
2450
|
}
|
|
@@ -2466,20 +2466,20 @@ function Carousel({
|
|
|
2466
2466
|
},
|
|
2467
2467
|
plugins
|
|
2468
2468
|
);
|
|
2469
|
-
const [canScrollPrev, setCanScrollPrev] =
|
|
2470
|
-
const [canScrollNext, setCanScrollNext] =
|
|
2471
|
-
const onSelect =
|
|
2469
|
+
const [canScrollPrev, setCanScrollPrev] = React29__namespace.useState(false);
|
|
2470
|
+
const [canScrollNext, setCanScrollNext] = React29__namespace.useState(false);
|
|
2471
|
+
const onSelect = React29__namespace.useCallback((api2) => {
|
|
2472
2472
|
if (!api2) return;
|
|
2473
2473
|
setCanScrollPrev(api2.canScrollPrev());
|
|
2474
2474
|
setCanScrollNext(api2.canScrollNext());
|
|
2475
2475
|
}, []);
|
|
2476
|
-
const scrollPrev =
|
|
2476
|
+
const scrollPrev = React29__namespace.useCallback(() => {
|
|
2477
2477
|
api?.scrollPrev();
|
|
2478
2478
|
}, [api]);
|
|
2479
|
-
const scrollNext =
|
|
2479
|
+
const scrollNext = React29__namespace.useCallback(() => {
|
|
2480
2480
|
api?.scrollNext();
|
|
2481
2481
|
}, [api]);
|
|
2482
|
-
const handleKeyDown =
|
|
2482
|
+
const handleKeyDown = React29__namespace.useCallback(
|
|
2483
2483
|
(event) => {
|
|
2484
2484
|
if (event.key === "ArrowLeft") {
|
|
2485
2485
|
event.preventDefault();
|
|
@@ -2491,11 +2491,11 @@ function Carousel({
|
|
|
2491
2491
|
},
|
|
2492
2492
|
[scrollPrev, scrollNext]
|
|
2493
2493
|
);
|
|
2494
|
-
|
|
2494
|
+
React29__namespace.useEffect(() => {
|
|
2495
2495
|
if (!api || !setApi) return;
|
|
2496
2496
|
setApi(api);
|
|
2497
2497
|
}, [api, setApi]);
|
|
2498
|
-
|
|
2498
|
+
React29__namespace.useEffect(() => {
|
|
2499
2499
|
if (!api) return;
|
|
2500
2500
|
onSelect(api);
|
|
2501
2501
|
api.on("reInit", onSelect);
|
|
@@ -2628,9 +2628,9 @@ function CarouselNext({
|
|
|
2628
2628
|
);
|
|
2629
2629
|
}
|
|
2630
2630
|
var THEMES = { light: "", dark: ".dark" };
|
|
2631
|
-
var ChartContext =
|
|
2631
|
+
var ChartContext = React29__namespace.createContext(null);
|
|
2632
2632
|
function useChart() {
|
|
2633
|
-
const context =
|
|
2633
|
+
const context = React29__namespace.useContext(ChartContext);
|
|
2634
2634
|
if (!context) {
|
|
2635
2635
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
2636
2636
|
}
|
|
@@ -2643,7 +2643,7 @@ function ChartContainer({
|
|
|
2643
2643
|
config,
|
|
2644
2644
|
...props
|
|
2645
2645
|
}) {
|
|
2646
|
-
const uniqueId =
|
|
2646
|
+
const uniqueId = React29__namespace.useId();
|
|
2647
2647
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
2648
2648
|
return /* @__PURE__ */ jsxRuntime.jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2649
2649
|
"div",
|
|
@@ -2704,7 +2704,7 @@ function ChartTooltipContent({
|
|
|
2704
2704
|
labelKey
|
|
2705
2705
|
}) {
|
|
2706
2706
|
const { config } = useChart();
|
|
2707
|
-
const tooltipLabel =
|
|
2707
|
+
const tooltipLabel = React29__namespace.useMemo(() => {
|
|
2708
2708
|
if (hideLabel || !payload?.length) {
|
|
2709
2709
|
return null;
|
|
2710
2710
|
}
|
|
@@ -3459,6 +3459,144 @@ function CircularProgress({
|
|
|
3459
3459
|
}
|
|
3460
3460
|
);
|
|
3461
3461
|
}
|
|
3462
|
+
function getVariantFromProgress(value) {
|
|
3463
|
+
if (value >= 100) return "complete";
|
|
3464
|
+
if (value >= 50) return "normal";
|
|
3465
|
+
if (value > 0) return "warning";
|
|
3466
|
+
return "critical";
|
|
3467
|
+
}
|
|
3468
|
+
function getStatusColors(variant) {
|
|
3469
|
+
switch (variant) {
|
|
3470
|
+
case "complete":
|
|
3471
|
+
return {
|
|
3472
|
+
track: "bg-green-500/20 dark:bg-green-500/10",
|
|
3473
|
+
fill: "bg-green-500",
|
|
3474
|
+
text: "text-green-600 dark:text-green-400",
|
|
3475
|
+
icon: "text-green-600 dark:text-green-400"
|
|
3476
|
+
};
|
|
3477
|
+
case "normal":
|
|
3478
|
+
return {
|
|
3479
|
+
track: "bg-green-500/20 dark:bg-green-500/10",
|
|
3480
|
+
fill: "bg-green-500",
|
|
3481
|
+
text: "text-green-600 dark:text-green-400",
|
|
3482
|
+
icon: "text-green-600 dark:text-green-400"
|
|
3483
|
+
};
|
|
3484
|
+
case "warning":
|
|
3485
|
+
return {
|
|
3486
|
+
track: "bg-amber-500/20 dark:bg-amber-500/10",
|
|
3487
|
+
fill: "bg-amber-500",
|
|
3488
|
+
text: "text-amber-600 dark:text-amber-400",
|
|
3489
|
+
icon: "text-amber-600 dark:text-amber-400"
|
|
3490
|
+
};
|
|
3491
|
+
case "critical":
|
|
3492
|
+
return {
|
|
3493
|
+
track: "bg-red-500/20 dark:bg-red-500/10",
|
|
3494
|
+
fill: "bg-red-500",
|
|
3495
|
+
text: "text-red-600 dark:text-red-400",
|
|
3496
|
+
icon: "text-red-600 dark:text-red-400"
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
function getSizeClasses(size) {
|
|
3501
|
+
switch (size) {
|
|
3502
|
+
case "sm":
|
|
3503
|
+
return {
|
|
3504
|
+
bar: "h-1",
|
|
3505
|
+
text: "text-[10px]",
|
|
3506
|
+
icon: "h-3 w-3",
|
|
3507
|
+
gap: "gap-1"
|
|
3508
|
+
};
|
|
3509
|
+
case "lg":
|
|
3510
|
+
return {
|
|
3511
|
+
bar: "h-3",
|
|
3512
|
+
text: "text-sm",
|
|
3513
|
+
icon: "h-5 w-5",
|
|
3514
|
+
gap: "gap-3"
|
|
3515
|
+
};
|
|
3516
|
+
default:
|
|
3517
|
+
return {
|
|
3518
|
+
bar: "h-2",
|
|
3519
|
+
text: "text-xs",
|
|
3520
|
+
icon: "h-4 w-4",
|
|
3521
|
+
gap: "gap-2"
|
|
3522
|
+
};
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
function StatusProgress({
|
|
3526
|
+
className,
|
|
3527
|
+
value,
|
|
3528
|
+
currentCount,
|
|
3529
|
+
totalCount,
|
|
3530
|
+
unitLabel = "elements",
|
|
3531
|
+
showLabel = false,
|
|
3532
|
+
showCheckmark = true,
|
|
3533
|
+
size = "md",
|
|
3534
|
+
variant,
|
|
3535
|
+
...props
|
|
3536
|
+
}) {
|
|
3537
|
+
const clampedValue = Math.min(100, Math.max(0, value));
|
|
3538
|
+
const isComplete = clampedValue >= 100;
|
|
3539
|
+
const resolvedVariant = variant ?? getVariantFromProgress(clampedValue);
|
|
3540
|
+
const colors = getStatusColors(resolvedVariant);
|
|
3541
|
+
const sizes = getSizeClasses(size);
|
|
3542
|
+
const labelText = React29__namespace.useMemo(() => {
|
|
3543
|
+
if (currentCount !== void 0 && totalCount !== void 0) {
|
|
3544
|
+
return `${currentCount} / ${totalCount} ${unitLabel}`;
|
|
3545
|
+
}
|
|
3546
|
+
return `${Math.round(clampedValue)}%`;
|
|
3547
|
+
}, [currentCount, totalCount, unitLabel, clampedValue]);
|
|
3548
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3549
|
+
"div",
|
|
3550
|
+
{
|
|
3551
|
+
"data-slot": "status-progress",
|
|
3552
|
+
"data-value": clampedValue,
|
|
3553
|
+
"data-variant": resolvedVariant,
|
|
3554
|
+
"data-complete": isComplete,
|
|
3555
|
+
className: cn("flex flex-col w-full", sizes.gap, className),
|
|
3556
|
+
...props,
|
|
3557
|
+
children: [
|
|
3558
|
+
showLabel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between", sizes.gap), children: [
|
|
3559
|
+
/* @__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: [
|
|
3560
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn(sizes.icon, colors.icon) }),
|
|
3561
|
+
"Complete"
|
|
3562
|
+
] }) : labelText }),
|
|
3563
|
+
!isComplete && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("tabular-nums text-muted-foreground", sizes.text), children: [
|
|
3564
|
+
Math.round(clampedValue),
|
|
3565
|
+
"%"
|
|
3566
|
+
] })
|
|
3567
|
+
] }),
|
|
3568
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3569
|
+
"div",
|
|
3570
|
+
{
|
|
3571
|
+
className: cn(
|
|
3572
|
+
"w-full rounded-full overflow-hidden",
|
|
3573
|
+
colors.track,
|
|
3574
|
+
sizes.bar
|
|
3575
|
+
),
|
|
3576
|
+
role: "progressbar",
|
|
3577
|
+
"aria-valuenow": clampedValue,
|
|
3578
|
+
"aria-valuemin": 0,
|
|
3579
|
+
"aria-valuemax": 100,
|
|
3580
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3581
|
+
"div",
|
|
3582
|
+
{
|
|
3583
|
+
className: cn(
|
|
3584
|
+
"h-full rounded-full transition-all duration-300 ease-out",
|
|
3585
|
+
colors.fill
|
|
3586
|
+
),
|
|
3587
|
+
style: { width: `${clampedValue}%` }
|
|
3588
|
+
}
|
|
3589
|
+
)
|
|
3590
|
+
}
|
|
3591
|
+
),
|
|
3592
|
+
!showLabel && isComplete && showCheckmark && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center", sizes.gap), children: [
|
|
3593
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn(sizes.icon, colors.icon) }),
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-medium", sizes.text, colors.text), children: "Complete" })
|
|
3595
|
+
] })
|
|
3596
|
+
]
|
|
3597
|
+
}
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3462
3600
|
function TooltipProvider({
|
|
3463
3601
|
delayDuration = 0,
|
|
3464
3602
|
...props
|
|
@@ -3506,8 +3644,8 @@ function TooltipContent({
|
|
|
3506
3644
|
) });
|
|
3507
3645
|
}
|
|
3508
3646
|
function useDetectTheme() {
|
|
3509
|
-
const [theme, setTheme] =
|
|
3510
|
-
|
|
3647
|
+
const [theme, setTheme] = React29__namespace.useState("light");
|
|
3648
|
+
React29__namespace.useEffect(() => {
|
|
3511
3649
|
const isDark = document.documentElement.classList.contains("dark");
|
|
3512
3650
|
setTheme(isDark ? "dark" : "light");
|
|
3513
3651
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -4156,7 +4294,7 @@ function CommandShortcut({
|
|
|
4156
4294
|
}
|
|
4157
4295
|
);
|
|
4158
4296
|
}
|
|
4159
|
-
var SearchTrigger =
|
|
4297
|
+
var SearchTrigger = React29__namespace.forwardRef(
|
|
4160
4298
|
({
|
|
4161
4299
|
className,
|
|
4162
4300
|
placeholder = "Search...",
|
|
@@ -4192,7 +4330,7 @@ var SearchTrigger = React27__namespace.forwardRef(
|
|
|
4192
4330
|
);
|
|
4193
4331
|
SearchTrigger.displayName = "SearchTrigger";
|
|
4194
4332
|
function useSearchShortcut(onOpen, key = "k") {
|
|
4195
|
-
|
|
4333
|
+
React29__namespace.useEffect(() => {
|
|
4196
4334
|
const down = (e) => {
|
|
4197
4335
|
if (e.key.toLowerCase() === key.toLowerCase() && (e.metaKey || e.ctrlKey)) {
|
|
4198
4336
|
e.preventDefault();
|
|
@@ -5167,9 +5305,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
5167
5305
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
5168
5306
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
5169
5307
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
5170
|
-
var SidebarContext =
|
|
5308
|
+
var SidebarContext = React29__namespace.createContext(null);
|
|
5171
5309
|
function useSidebar() {
|
|
5172
|
-
const context =
|
|
5310
|
+
const context = React29__namespace.useContext(SidebarContext);
|
|
5173
5311
|
if (!context) {
|
|
5174
5312
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
5175
5313
|
}
|
|
@@ -5185,10 +5323,10 @@ function SidebarProvider({
|
|
|
5185
5323
|
...props
|
|
5186
5324
|
}) {
|
|
5187
5325
|
const isMobile = useIsMobile();
|
|
5188
|
-
const [openMobile, setOpenMobile] =
|
|
5189
|
-
const [_open, _setOpen] =
|
|
5326
|
+
const [openMobile, setOpenMobile] = React29__namespace.useState(false);
|
|
5327
|
+
const [_open, _setOpen] = React29__namespace.useState(defaultOpen);
|
|
5190
5328
|
const open = openProp ?? _open;
|
|
5191
|
-
const setOpen =
|
|
5329
|
+
const setOpen = React29__namespace.useCallback(
|
|
5192
5330
|
(value) => {
|
|
5193
5331
|
const openState = typeof value === "function" ? value(open) : value;
|
|
5194
5332
|
if (setOpenProp) {
|
|
@@ -5200,10 +5338,10 @@ function SidebarProvider({
|
|
|
5200
5338
|
},
|
|
5201
5339
|
[setOpenProp, open]
|
|
5202
5340
|
);
|
|
5203
|
-
const toggleSidebar =
|
|
5341
|
+
const toggleSidebar = React29__namespace.useCallback(() => {
|
|
5204
5342
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
5205
5343
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
5206
|
-
|
|
5344
|
+
React29__namespace.useEffect(() => {
|
|
5207
5345
|
const handleKeyDown = (event) => {
|
|
5208
5346
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
5209
5347
|
event.preventDefault();
|
|
@@ -5214,7 +5352,7 @@ function SidebarProvider({
|
|
|
5214
5352
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
5215
5353
|
}, [toggleSidebar]);
|
|
5216
5354
|
const state = open ? "expanded" : "collapsed";
|
|
5217
|
-
const contextValue =
|
|
5355
|
+
const contextValue = React29__namespace.useMemo(
|
|
5218
5356
|
() => ({
|
|
5219
5357
|
state,
|
|
5220
5358
|
open,
|
|
@@ -5672,7 +5810,7 @@ function SidebarMenuSkeleton({
|
|
|
5672
5810
|
showIcon = false,
|
|
5673
5811
|
...props
|
|
5674
5812
|
}) {
|
|
5675
|
-
const width =
|
|
5813
|
+
const width = React29__namespace.useMemo(() => {
|
|
5676
5814
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
5677
5815
|
}, []);
|
|
5678
5816
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -5815,7 +5953,7 @@ var sectionVariants = classVarianceAuthority.cva(
|
|
|
5815
5953
|
}
|
|
5816
5954
|
);
|
|
5817
5955
|
var isGlassVariant = (variant) => variant?.startsWith("glass-") ?? false;
|
|
5818
|
-
var Section =
|
|
5956
|
+
var Section = React29__namespace.forwardRef(
|
|
5819
5957
|
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5820
5958
|
"section",
|
|
5821
5959
|
{
|
|
@@ -5827,7 +5965,7 @@ var Section = React27__namespace.forwardRef(
|
|
|
5827
5965
|
)
|
|
5828
5966
|
);
|
|
5829
5967
|
Section.displayName = "Section";
|
|
5830
|
-
var SectionHeader =
|
|
5968
|
+
var SectionHeader = React29__namespace.forwardRef(
|
|
5831
5969
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5832
5970
|
"div",
|
|
5833
5971
|
{
|
|
@@ -5842,7 +5980,7 @@ var SectionHeader = React27__namespace.forwardRef(
|
|
|
5842
5980
|
)
|
|
5843
5981
|
);
|
|
5844
5982
|
SectionHeader.displayName = "SectionHeader";
|
|
5845
|
-
var SectionTitle =
|
|
5983
|
+
var SectionTitle = React29__namespace.forwardRef(
|
|
5846
5984
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5847
5985
|
"h2",
|
|
5848
5986
|
{
|
|
@@ -5856,7 +5994,7 @@ var SectionTitle = React27__namespace.forwardRef(
|
|
|
5856
5994
|
)
|
|
5857
5995
|
);
|
|
5858
5996
|
SectionTitle.displayName = "SectionTitle";
|
|
5859
|
-
var SectionDescription =
|
|
5997
|
+
var SectionDescription = React29__namespace.forwardRef(
|
|
5860
5998
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5861
5999
|
"p",
|
|
5862
6000
|
{
|
|
@@ -5870,7 +6008,7 @@ var SectionDescription = React27__namespace.forwardRef(
|
|
|
5870
6008
|
)
|
|
5871
6009
|
);
|
|
5872
6010
|
SectionDescription.displayName = "SectionDescription";
|
|
5873
|
-
var SectionContent =
|
|
6011
|
+
var SectionContent = React29__namespace.forwardRef(
|
|
5874
6012
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5875
6013
|
"div",
|
|
5876
6014
|
{
|
|
@@ -5884,7 +6022,7 @@ var SectionContent = React27__namespace.forwardRef(
|
|
|
5884
6022
|
)
|
|
5885
6023
|
);
|
|
5886
6024
|
SectionContent.displayName = "SectionContent";
|
|
5887
|
-
var SectionFooter =
|
|
6025
|
+
var SectionFooter = React29__namespace.forwardRef(
|
|
5888
6026
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5889
6027
|
"div",
|
|
5890
6028
|
{
|
|
@@ -6192,7 +6330,7 @@ function SiteHeader({
|
|
|
6192
6330
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[var(--header-height,3.5rem)] w-full items-center gap-[var(--j3m-spacing-s)] px-[var(--j3m-spacing-m)]", children: [
|
|
6193
6331
|
trigger,
|
|
6194
6332
|
trigger && /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "mr-[var(--j3m-spacing-s)] h-4" }),
|
|
6195
|
-
/* @__PURE__ */ jsxRuntime.jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6333
|
+
/* @__PURE__ */ jsxRuntime.jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(React29__namespace.Fragment, { children: [
|
|
6196
6334
|
index > 0 && /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbSeparator, {}),
|
|
6197
6335
|
/* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { children: item.href ? /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbPage, { children: item.label }) })
|
|
6198
6336
|
] }, index)) }) }),
|
|
@@ -6431,15 +6569,27 @@ function getCombinedRiskLevel(data) {
|
|
|
6431
6569
|
if (productionStatus === "delayed" || hasDeliveryDelayed || data.hasWarning) {
|
|
6432
6570
|
return "warning";
|
|
6433
6571
|
}
|
|
6572
|
+
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6573
|
+
const isProductionComplete = productionProgress >= 100;
|
|
6574
|
+
if (isProductionComplete) {
|
|
6575
|
+
return "complete";
|
|
6576
|
+
}
|
|
6434
6577
|
return "normal";
|
|
6435
6578
|
}
|
|
6436
|
-
function getRowStatus(status) {
|
|
6579
|
+
function getRowStatus(status, progress) {
|
|
6437
6580
|
if (status === "critical") return "critical";
|
|
6438
6581
|
if (status === "delayed") return "warning";
|
|
6582
|
+
if (progress !== void 0 && progress >= 100) return "complete";
|
|
6439
6583
|
return "normal";
|
|
6440
6584
|
}
|
|
6441
6585
|
var statusFillClasses = {
|
|
6442
6586
|
normal: {
|
|
6587
|
+
// Grey/muted for "on track but not complete" - reduces visual noise
|
|
6588
|
+
border: "border-l-[3px] border-l-muted-foreground/40",
|
|
6589
|
+
bg: "bg-muted/30 dark:bg-muted/20"
|
|
6590
|
+
},
|
|
6591
|
+
complete: {
|
|
6592
|
+
// Green for "done/complete" - clear success signal
|
|
6443
6593
|
border: "border-l-[3px] border-l-green-500",
|
|
6444
6594
|
bg: "bg-green-50/50 dark:bg-green-950/30"
|
|
6445
6595
|
},
|
|
@@ -6454,6 +6604,13 @@ var statusFillClasses = {
|
|
|
6454
6604
|
};
|
|
6455
6605
|
var statusColors = {
|
|
6456
6606
|
normal: {
|
|
6607
|
+
// Grey/muted for "on track but not complete"
|
|
6608
|
+
icon: "text-muted-foreground",
|
|
6609
|
+
progress: "bg-muted-foreground/60",
|
|
6610
|
+
text: "text-muted-foreground"
|
|
6611
|
+
},
|
|
6612
|
+
complete: {
|
|
6613
|
+
// Green for "done/complete"
|
|
6457
6614
|
icon: "text-green-600 dark:text-green-400",
|
|
6458
6615
|
progress: "bg-green-500",
|
|
6459
6616
|
text: "text-green-700 dark:text-green-300"
|
|
@@ -6481,19 +6638,20 @@ function WeekCell({
|
|
|
6481
6638
|
const combinedRisk = data.type === "data" ? getCombinedRiskLevel(data) : "normal";
|
|
6482
6639
|
const statusClasses = statusFillClasses[combinedRisk];
|
|
6483
6640
|
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6484
|
-
const productionStatus = getRowStatus(data.production?.status);
|
|
6641
|
+
const productionStatus = getRowStatus(data.production?.status, productionProgress);
|
|
6485
6642
|
const productionColors = statusColors[productionStatus];
|
|
6486
6643
|
const deliveryCount = data.deliveries?.length ?? 0;
|
|
6487
|
-
const
|
|
6644
|
+
const allDeliveriesComplete = data.deliveries?.every((d) => (d.progress ?? 0) >= 100) ?? false;
|
|
6645
|
+
const worstDeliveryStatus = data.deliveries?.some((d) => d.status === "critical") ? "critical" : data.deliveries?.some((d) => d.status === "delayed") ? "warning" : allDeliveriesComplete && deliveryCount > 0 ? "complete" : "normal";
|
|
6488
6646
|
const deliveryColors = statusColors[worstDeliveryStatus];
|
|
6489
|
-
const getDeliveryStatusColor = (
|
|
6490
|
-
switch (status) {
|
|
6647
|
+
const getDeliveryStatusColor = (delivery) => {
|
|
6648
|
+
switch (delivery.status) {
|
|
6491
6649
|
case "critical":
|
|
6492
6650
|
return "bg-red-500";
|
|
6493
6651
|
case "delayed":
|
|
6494
6652
|
return "bg-amber-500";
|
|
6495
6653
|
default:
|
|
6496
|
-
return "bg-green-500";
|
|
6654
|
+
return (delivery.progress ?? 0) >= 100 ? "bg-green-500" : "bg-muted-foreground/60";
|
|
6497
6655
|
}
|
|
6498
6656
|
};
|
|
6499
6657
|
const handleClick = () => {
|
|
@@ -6610,24 +6768,18 @@ function WeekCell({
|
|
|
6610
6768
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2014" })
|
|
6611
6769
|
] }),
|
|
6612
6770
|
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
|
-
}),
|
|
6771
|
+
data.deliveries?.slice(0, 5).map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6772
|
+
"div",
|
|
6773
|
+
{
|
|
6774
|
+
className: cn(
|
|
6775
|
+
"flex-1 max-w-[24px] h-1.5 rounded-full",
|
|
6776
|
+
// Solid status color - grey=on-track, green=complete, amber=at-risk, red=critical
|
|
6777
|
+
getDeliveryStatusColor(delivery)
|
|
6778
|
+
),
|
|
6779
|
+
title: delivery.label || `Delivery ${index + 1}`
|
|
6780
|
+
},
|
|
6781
|
+
delivery.id || index
|
|
6782
|
+
)),
|
|
6631
6783
|
deliveryCount > 5 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[8px] text-muted-foreground", children: [
|
|
6632
6784
|
"+",
|
|
6633
6785
|
deliveryCount - 5
|
|
@@ -6799,11 +6951,11 @@ function PlanningWeekCommentPopover({
|
|
|
6799
6951
|
open,
|
|
6800
6952
|
onOpenChange
|
|
6801
6953
|
}) {
|
|
6802
|
-
const [newCommentText, setNewCommentText] =
|
|
6803
|
-
const [selectedLocationId, setSelectedLocationId] =
|
|
6804
|
-
const [viewCommentsOpen, setViewCommentsOpen] =
|
|
6805
|
-
const [showAddForm, setShowAddForm] =
|
|
6806
|
-
const selectedLocation =
|
|
6954
|
+
const [newCommentText, setNewCommentText] = React29__namespace.useState("");
|
|
6955
|
+
const [selectedLocationId, setSelectedLocationId] = React29__namespace.useState("");
|
|
6956
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React29__namespace.useState(true);
|
|
6957
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
6958
|
+
const selectedLocation = React29__namespace.useMemo(() => {
|
|
6807
6959
|
return locationOptions.find((opt) => opt.id === selectedLocationId);
|
|
6808
6960
|
}, [locationOptions, selectedLocationId]);
|
|
6809
6961
|
const handleSubmit = () => {
|
|
@@ -6847,8 +6999,8 @@ function PlanningWeekCommentPopover({
|
|
|
6847
6999
|
minute: "2-digit"
|
|
6848
7000
|
}).format(date);
|
|
6849
7001
|
};
|
|
6850
|
-
const prevOpenRef =
|
|
6851
|
-
|
|
7002
|
+
const prevOpenRef = React29__namespace.useRef(open);
|
|
7003
|
+
React29__namespace.useEffect(() => {
|
|
6852
7004
|
const wasOpen = prevOpenRef.current;
|
|
6853
7005
|
prevOpenRef.current = open;
|
|
6854
7006
|
if (wasOpen && !open) {
|
|
@@ -7202,22 +7354,22 @@ function PlanningTable({
|
|
|
7202
7354
|
stickySupplierColumn = true,
|
|
7203
7355
|
maxHeight = "600px"
|
|
7204
7356
|
} = config;
|
|
7205
|
-
const weeks =
|
|
7357
|
+
const weeks = React29__namespace.useMemo(
|
|
7206
7358
|
() => generateWeeks(startDate, weekCount),
|
|
7207
7359
|
[startDate, weekCount]
|
|
7208
7360
|
);
|
|
7209
|
-
const currentWeekKey =
|
|
7361
|
+
const currentWeekKey = React29__namespace.useMemo(() => {
|
|
7210
7362
|
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
7211
7363
|
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
7212
7364
|
}, [weeks]);
|
|
7213
|
-
const columns =
|
|
7365
|
+
const columns = React29__namespace.useMemo(
|
|
7214
7366
|
() => generateColumns(weeks, config, suppliers),
|
|
7215
7367
|
[weeks, config, suppliers]
|
|
7216
7368
|
);
|
|
7217
|
-
const [sorting, setSorting] =
|
|
7218
|
-
const [columnFilters, setColumnFilters] =
|
|
7219
|
-
const [columnVisibility, setColumnVisibility] =
|
|
7220
|
-
const [rowSelection, setRowSelection] =
|
|
7369
|
+
const [sorting, setSorting] = React29__namespace.useState([]);
|
|
7370
|
+
const [columnFilters, setColumnFilters] = React29__namespace.useState([]);
|
|
7371
|
+
const [columnVisibility, setColumnVisibility] = React29__namespace.useState({});
|
|
7372
|
+
const [rowSelection, setRowSelection] = React29__namespace.useState({});
|
|
7221
7373
|
const table = reactTable.useReactTable({
|
|
7222
7374
|
data: suppliers,
|
|
7223
7375
|
columns,
|
|
@@ -7340,10 +7492,12 @@ function PlanningTable({
|
|
|
7340
7492
|
}
|
|
7341
7493
|
);
|
|
7342
7494
|
}
|
|
7343
|
-
function getStatusBadgeVariant(status) {
|
|
7495
|
+
function getStatusBadgeVariant(status, isComplete) {
|
|
7496
|
+
if (isComplete) return "outline";
|
|
7344
7497
|
switch (status) {
|
|
7345
7498
|
case "on-time":
|
|
7346
7499
|
return "outline";
|
|
7500
|
+
// Grey for on-track
|
|
7347
7501
|
case "delayed":
|
|
7348
7502
|
return "secondary";
|
|
7349
7503
|
case "critical":
|
|
@@ -7352,19 +7506,24 @@ function getStatusBadgeVariant(status) {
|
|
|
7352
7506
|
return "outline";
|
|
7353
7507
|
}
|
|
7354
7508
|
}
|
|
7355
|
-
function getStatusBadgeClasses(status) {
|
|
7509
|
+
function getStatusBadgeClasses(status, isComplete) {
|
|
7510
|
+
if (isComplete) {
|
|
7511
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7512
|
+
}
|
|
7356
7513
|
switch (status) {
|
|
7357
7514
|
case "on-time":
|
|
7358
|
-
return "border-
|
|
7515
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
7516
|
+
// Grey for on-track
|
|
7359
7517
|
case "delayed":
|
|
7360
7518
|
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
7361
7519
|
case "critical":
|
|
7362
7520
|
return "";
|
|
7363
7521
|
default:
|
|
7364
|
-
return "";
|
|
7522
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
7365
7523
|
}
|
|
7366
7524
|
}
|
|
7367
|
-
function getStatusLabel(status) {
|
|
7525
|
+
function getStatusLabel(status, isComplete) {
|
|
7526
|
+
if (isComplete) return "Complete";
|
|
7368
7527
|
switch (status) {
|
|
7369
7528
|
case "on-time":
|
|
7370
7529
|
return "On Track";
|
|
@@ -7378,10 +7537,12 @@ function getStatusLabel(status) {
|
|
|
7378
7537
|
return status;
|
|
7379
7538
|
}
|
|
7380
7539
|
}
|
|
7381
|
-
function getProgressVariant(status) {
|
|
7540
|
+
function getProgressVariant(status, isComplete) {
|
|
7541
|
+
if (isComplete) return "success";
|
|
7382
7542
|
switch (status) {
|
|
7383
7543
|
case "on-time":
|
|
7384
|
-
return "
|
|
7544
|
+
return "default";
|
|
7545
|
+
// Grey/default for on-track
|
|
7385
7546
|
case "delayed":
|
|
7386
7547
|
return "warning";
|
|
7387
7548
|
case "critical":
|
|
@@ -7424,10 +7585,10 @@ function DeliveryCommentPopover({
|
|
|
7424
7585
|
onAddComment,
|
|
7425
7586
|
deliveryLabel
|
|
7426
7587
|
}) {
|
|
7427
|
-
const [open, setOpen] =
|
|
7428
|
-
const [newCommentText, setNewCommentText] =
|
|
7429
|
-
const [viewCommentsOpen, setViewCommentsOpen] =
|
|
7430
|
-
const [showAddForm, setShowAddForm] =
|
|
7588
|
+
const [open, setOpen] = React29__namespace.useState(false);
|
|
7589
|
+
const [newCommentText, setNewCommentText] = React29__namespace.useState("");
|
|
7590
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React29__namespace.useState(true);
|
|
7591
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
7431
7592
|
const handleSubmit = () => {
|
|
7432
7593
|
if (newCommentText.trim() && onAddComment) {
|
|
7433
7594
|
onAddComment(newCommentText.trim());
|
|
@@ -7454,8 +7615,8 @@ function DeliveryCommentPopover({
|
|
|
7454
7615
|
minute: "2-digit"
|
|
7455
7616
|
}).format(date);
|
|
7456
7617
|
};
|
|
7457
|
-
const prevOpenRef =
|
|
7458
|
-
|
|
7618
|
+
const prevOpenRef = React29__namespace.useRef(open);
|
|
7619
|
+
React29__namespace.useEffect(() => {
|
|
7459
7620
|
const wasOpen = prevOpenRef.current;
|
|
7460
7621
|
prevOpenRef.current = open;
|
|
7461
7622
|
if (wasOpen && !open) {
|
|
@@ -7567,8 +7728,8 @@ function ProductionCommentSection({
|
|
|
7567
7728
|
comments = [],
|
|
7568
7729
|
onAddComment
|
|
7569
7730
|
}) {
|
|
7570
|
-
const [showAddForm, setShowAddForm] =
|
|
7571
|
-
const [newComment, setNewComment] =
|
|
7731
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
7732
|
+
const [newComment, setNewComment] = React29__namespace.useState("");
|
|
7572
7733
|
const handleSubmit = () => {
|
|
7573
7734
|
if (newComment.trim() && onAddComment) {
|
|
7574
7735
|
onAddComment(newComment.trim());
|
|
@@ -7666,6 +7827,20 @@ function DeliveryListItem({
|
|
|
7666
7827
|
onClick
|
|
7667
7828
|
}) {
|
|
7668
7829
|
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
7830
|
+
const isComplete = (delivery.progress ?? 0) >= 100;
|
|
7831
|
+
const getIconStyles = () => {
|
|
7832
|
+
if (delivery.status === "critical") {
|
|
7833
|
+
return { bg: "bg-red-100 dark:bg-red-950/50", icon: "text-red-600 dark:text-red-400" };
|
|
7834
|
+
}
|
|
7835
|
+
if (delivery.status === "delayed") {
|
|
7836
|
+
return { bg: "bg-amber-100 dark:bg-amber-950/50", icon: "text-amber-600 dark:text-amber-400" };
|
|
7837
|
+
}
|
|
7838
|
+
if (isComplete) {
|
|
7839
|
+
return { bg: "bg-green-100 dark:bg-green-950/50", icon: "text-green-600 dark:text-green-400" };
|
|
7840
|
+
}
|
|
7841
|
+
return { bg: "bg-muted", icon: "text-muted-foreground" };
|
|
7842
|
+
};
|
|
7843
|
+
const iconStyles = getIconStyles();
|
|
7669
7844
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7670
7845
|
"button",
|
|
7671
7846
|
{
|
|
@@ -7679,15 +7854,8 @@ function DeliveryListItem({
|
|
|
7679
7854
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7680
7855
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
7681
7856
|
"flex items-center justify-center h-8 w-8 rounded-lg",
|
|
7682
|
-
|
|
7683
|
-
|
|
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
|
-
) }) }),
|
|
7857
|
+
iconStyles.bg
|
|
7858
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-4 w-4", iconStyles.icon) }) }),
|
|
7691
7859
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7692
7860
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7693
7861
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: delivery.label || `Delivery ${index + 1}` }),
|
|
@@ -7706,9 +7874,9 @@ function DeliveryListItem({
|
|
|
7706
7874
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
7875
|
Badge,
|
|
7708
7876
|
{
|
|
7709
|
-
variant: getStatusBadgeVariant(delivery.status),
|
|
7710
|
-
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7711
|
-
children: getStatusLabel(delivery.status)
|
|
7877
|
+
variant: getStatusBadgeVariant(delivery.status, isComplete),
|
|
7878
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status, isComplete)),
|
|
7879
|
+
children: getStatusLabel(delivery.status, isComplete)
|
|
7712
7880
|
}
|
|
7713
7881
|
),
|
|
7714
7882
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
@@ -7724,7 +7892,7 @@ function DeliveryDetailsView({
|
|
|
7724
7892
|
onAddComment
|
|
7725
7893
|
}) {
|
|
7726
7894
|
const elements = delivery.elements ?? [];
|
|
7727
|
-
const categorizedElements =
|
|
7895
|
+
const categorizedElements = React29__namespace.useMemo(() => {
|
|
7728
7896
|
const sent = [];
|
|
7729
7897
|
const notSent = [];
|
|
7730
7898
|
const moved = [];
|
|
@@ -7782,9 +7950,9 @@ function DeliveryDetailsView({
|
|
|
7782
7950
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7783
7951
|
Badge,
|
|
7784
7952
|
{
|
|
7785
|
-
variant: getStatusBadgeVariant(delivery.status),
|
|
7786
|
-
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7787
|
-
children: getStatusLabel(delivery.status)
|
|
7953
|
+
variant: getStatusBadgeVariant(delivery.status, sentCount === totalCount && totalCount > 0),
|
|
7954
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status, sentCount === totalCount && totalCount > 0)),
|
|
7955
|
+
children: getStatusLabel(delivery.status, sentCount === totalCount && totalCount > 0)
|
|
7788
7956
|
}
|
|
7789
7957
|
)
|
|
7790
7958
|
] })
|
|
@@ -7957,9 +8125,9 @@ function MainView({
|
|
|
7957
8125
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7958
8126
|
Badge,
|
|
7959
8127
|
{
|
|
7960
|
-
variant: getStatusBadgeVariant(productionStatus),
|
|
7961
|
-
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus)),
|
|
7962
|
-
children: getStatusLabel(productionStatus)
|
|
8128
|
+
variant: getStatusBadgeVariant(productionStatus, isComplete),
|
|
8129
|
+
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus, isComplete)),
|
|
8130
|
+
children: getStatusLabel(productionStatus, isComplete)
|
|
7963
8131
|
}
|
|
7964
8132
|
)
|
|
7965
8133
|
] }),
|
|
@@ -7970,7 +8138,7 @@ function MainView({
|
|
|
7970
8138
|
value: productionProgress,
|
|
7971
8139
|
size: 100,
|
|
7972
8140
|
strokeWidth: 10,
|
|
7973
|
-
variant: getProgressVariant(productionStatus),
|
|
8141
|
+
variant: getProgressVariant(productionStatus, isComplete),
|
|
7974
8142
|
showCheckmark: isComplete,
|
|
7975
8143
|
children: isComplete ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7976
8144
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-6 w-6 text-green-600" }),
|
|
@@ -8092,15 +8260,15 @@ function WeekDetailDialog({
|
|
|
8092
8260
|
}) {
|
|
8093
8261
|
const production = data?.production;
|
|
8094
8262
|
const initialProduced = production?.produced ?? 0;
|
|
8095
|
-
const [producedValue, setProducedValue] =
|
|
8096
|
-
const [hasChanges, setHasChanges] =
|
|
8097
|
-
const [selectedDelivery, setSelectedDelivery] =
|
|
8098
|
-
|
|
8263
|
+
const [producedValue, setProducedValue] = React29__namespace.useState(initialProduced.toString());
|
|
8264
|
+
const [hasChanges, setHasChanges] = React29__namespace.useState(false);
|
|
8265
|
+
const [selectedDelivery, setSelectedDelivery] = React29__namespace.useState(null);
|
|
8266
|
+
React29__namespace.useEffect(() => {
|
|
8099
8267
|
const newProduced = data?.production?.produced ?? 0;
|
|
8100
8268
|
setProducedValue(newProduced.toString());
|
|
8101
8269
|
setHasChanges(false);
|
|
8102
8270
|
}, [data]);
|
|
8103
|
-
|
|
8271
|
+
React29__namespace.useEffect(() => {
|
|
8104
8272
|
if (!open) {
|
|
8105
8273
|
setSelectedDelivery(null);
|
|
8106
8274
|
}
|
|
@@ -8151,59 +8319,1074 @@ function WeekDetailDialog({
|
|
|
8151
8319
|
}
|
|
8152
8320
|
) }) });
|
|
8153
8321
|
}
|
|
8154
|
-
function
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8322
|
+
function getStatusBadgeVariant2(status, isComplete) {
|
|
8323
|
+
if (isComplete) return "outline";
|
|
8324
|
+
switch (status) {
|
|
8325
|
+
case "on-time":
|
|
8326
|
+
return "outline";
|
|
8327
|
+
// Grey for on-track
|
|
8328
|
+
case "delayed":
|
|
8329
|
+
return "secondary";
|
|
8330
|
+
case "critical":
|
|
8331
|
+
return "destructive";
|
|
8332
|
+
default:
|
|
8333
|
+
return "outline";
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
8336
|
+
function getStatusBadgeClasses2(status, isComplete) {
|
|
8337
|
+
if (isComplete) {
|
|
8338
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
8339
|
+
}
|
|
8340
|
+
switch (status) {
|
|
8341
|
+
case "on-time":
|
|
8342
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
8343
|
+
// Grey for on-track
|
|
8344
|
+
case "delayed":
|
|
8345
|
+
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
8346
|
+
case "critical":
|
|
8347
|
+
return "";
|
|
8348
|
+
default:
|
|
8349
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
function getStatusLabel2(status, isComplete) {
|
|
8353
|
+
if (isComplete) return "Complete";
|
|
8354
|
+
switch (status) {
|
|
8355
|
+
case "on-time":
|
|
8356
|
+
return "On Track";
|
|
8357
|
+
case "delayed":
|
|
8358
|
+
return "At Risk";
|
|
8359
|
+
case "critical":
|
|
8360
|
+
return "Critical";
|
|
8361
|
+
case "pending":
|
|
8362
|
+
return "Pending";
|
|
8363
|
+
default:
|
|
8364
|
+
return status;
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
function getShipmentStatusBadgeClasses2(status) {
|
|
8368
|
+
switch (status) {
|
|
8369
|
+
case "sent":
|
|
8370
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
8371
|
+
case "not-sent":
|
|
8372
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
8373
|
+
case "moved":
|
|
8374
|
+
return "border-blue-500 text-blue-600 bg-blue-50 dark:bg-blue-950/50";
|
|
8375
|
+
case "addon":
|
|
8376
|
+
return "border-purple-500 text-purple-600 bg-purple-50 dark:bg-purple-950/50";
|
|
8377
|
+
case "planned":
|
|
8378
|
+
default:
|
|
8379
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8382
|
+
function getShipmentStatusRowBg2(status) {
|
|
8383
|
+
switch (status) {
|
|
8384
|
+
case "sent":
|
|
8385
|
+
return "bg-green-50/30 dark:bg-green-950/10";
|
|
8386
|
+
case "not-sent":
|
|
8387
|
+
return "bg-muted/30";
|
|
8388
|
+
case "moved":
|
|
8389
|
+
return "bg-blue-50/30 dark:bg-blue-950/10";
|
|
8390
|
+
case "addon":
|
|
8391
|
+
return "bg-purple-50/30 dark:bg-purple-950/10";
|
|
8392
|
+
default:
|
|
8393
|
+
return "";
|
|
8394
|
+
}
|
|
8395
|
+
}
|
|
8396
|
+
function ElementProductionDialog({
|
|
8397
|
+
open,
|
|
8398
|
+
onOpenChange,
|
|
8399
|
+
elements,
|
|
8400
|
+
onSave
|
|
8159
8401
|
}) {
|
|
8160
|
-
const
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8402
|
+
const [searchQuery, setSearchQuery] = React29__namespace.useState("");
|
|
8403
|
+
const [selectedIds, setSelectedIds] = React29__namespace.useState(
|
|
8404
|
+
new Set(elements.filter((e) => e.isProduced).map((e) => e.id))
|
|
8405
|
+
);
|
|
8406
|
+
React29__namespace.useEffect(() => {
|
|
8407
|
+
if (open) {
|
|
8408
|
+
setSelectedIds(new Set(elements.filter((e) => e.isProduced).map((e) => e.id)));
|
|
8409
|
+
setSearchQuery("");
|
|
8410
|
+
}
|
|
8411
|
+
}, [open, elements]);
|
|
8412
|
+
const filteredElements = React29__namespace.useMemo(() => {
|
|
8413
|
+
if (!searchQuery.trim()) return elements;
|
|
8414
|
+
const query = searchQuery.toLowerCase();
|
|
8415
|
+
return elements.filter(
|
|
8416
|
+
(e) => e.name.toLowerCase().includes(query) || e.prefix?.toLowerCase().includes(query) || e.type?.toLowerCase().includes(query)
|
|
8417
|
+
);
|
|
8418
|
+
}, [elements, searchQuery]);
|
|
8419
|
+
React29__namespace.useMemo(() => {
|
|
8420
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
8421
|
+
elements.forEach((e) => {
|
|
8422
|
+
if (e.prefix) prefixes.add(e.prefix);
|
|
8423
|
+
});
|
|
8424
|
+
return Array.from(prefixes).sort();
|
|
8425
|
+
}, [elements]);
|
|
8426
|
+
const toggleElement = (id) => {
|
|
8427
|
+
setSelectedIds((prev) => {
|
|
8428
|
+
const next = new Set(prev);
|
|
8429
|
+
if (next.has(id)) {
|
|
8430
|
+
next.delete(id);
|
|
8431
|
+
} else {
|
|
8432
|
+
next.add(id);
|
|
8433
|
+
}
|
|
8434
|
+
return next;
|
|
8435
|
+
});
|
|
8436
|
+
};
|
|
8437
|
+
const selectAll = () => {
|
|
8438
|
+
setSelectedIds(new Set(filteredElements.map((e) => e.id)));
|
|
8439
|
+
};
|
|
8440
|
+
const deselectAll = () => {
|
|
8441
|
+
setSelectedIds(/* @__PURE__ */ new Set());
|
|
8442
|
+
};
|
|
8443
|
+
const handleSave = () => {
|
|
8444
|
+
onSave(Array.from(selectedIds));
|
|
8445
|
+
onOpenChange(false);
|
|
8446
|
+
};
|
|
8447
|
+
const selectedCount = selectedIds.size;
|
|
8448
|
+
const totalCount = elements.length;
|
|
8449
|
+
const selectedWeight = elements.filter((e) => selectedIds.has(e.id)).reduce((sum, e) => sum + (e.weight ?? 0), 0);
|
|
8450
|
+
const totalWeight = elements.reduce((sum, e) => sum + (e.weight ?? 0), 0);
|
|
8451
|
+
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: [
|
|
8452
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "w-full p-6 pb-0 shrink-0", children: [
|
|
8453
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Enter production progress" }),
|
|
8454
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
8455
|
+
"Mark elements as produced (",
|
|
8456
|
+
selectedCount,
|
|
8457
|
+
" / ",
|
|
8458
|
+
totalCount,
|
|
8459
|
+
" selected)"
|
|
8460
|
+
] })
|
|
8461
|
+
] }),
|
|
8462
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col p-6 pt-4 gap-4 overflow-hidden w-fit", children: [
|
|
8463
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-3 shrink-0", children: [
|
|
8464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
|
|
8465
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
8466
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8467
|
+
Input,
|
|
8178
8468
|
{
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
"Paint"
|
|
8184
|
-
]
|
|
8469
|
+
placeholder: "Search elements...",
|
|
8470
|
+
value: searchQuery,
|
|
8471
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
8472
|
+
className: "pl-9 w-full"
|
|
8185
8473
|
}
|
|
8186
8474
|
)
|
|
8187
8475
|
] }),
|
|
8188
|
-
|
|
8189
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8190
|
-
|
|
8476
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
8477
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8478
|
+
Button,
|
|
8191
8479
|
{
|
|
8192
|
-
|
|
8193
|
-
|
|
8480
|
+
variant: "outline",
|
|
8481
|
+
size: "sm",
|
|
8482
|
+
onClick: selectAll,
|
|
8483
|
+
children: "Select all"
|
|
8484
|
+
}
|
|
8485
|
+
),
|
|
8486
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8487
|
+
Button,
|
|
8488
|
+
{
|
|
8489
|
+
variant: "outline",
|
|
8490
|
+
size: "sm",
|
|
8491
|
+
onClick: deselectAll,
|
|
8492
|
+
children: "Deselect all"
|
|
8493
|
+
}
|
|
8494
|
+
)
|
|
8495
|
+
] })
|
|
8496
|
+
] }),
|
|
8497
|
+
/* @__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: [
|
|
8498
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { className: "sticky top-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "bg-muted/50 hover:bg-muted/50", children: [
|
|
8499
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-[44px] bg-muted/50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8500
|
+
Checkbox,
|
|
8501
|
+
{
|
|
8502
|
+
checked: selectedIds.size === filteredElements.length && filteredElements.length > 0,
|
|
8503
|
+
onCheckedChange: (checked) => {
|
|
8504
|
+
if (checked) {
|
|
8505
|
+
selectAll();
|
|
8506
|
+
} else {
|
|
8507
|
+
deselectAll();
|
|
8508
|
+
}
|
|
8509
|
+
},
|
|
8510
|
+
"aria-label": "Select all elements"
|
|
8194
8511
|
}
|
|
8195
8512
|
) }),
|
|
8196
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8197
|
-
|
|
8513
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50", children: "Element" }),
|
|
8514
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 w-[80px]", children: "Type" }),
|
|
8515
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-right w-[90px]", children: "Weight" }),
|
|
8516
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-right w-[80px]", children: "Size" }),
|
|
8517
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "bg-muted/50 text-center w-[100px]", children: "Status" })
|
|
8518
|
+
] }) }),
|
|
8519
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: filteredElements.map((element) => {
|
|
8520
|
+
const isSelected = selectedIds.has(element.id);
|
|
8521
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8522
|
+
TableRow,
|
|
8523
|
+
{
|
|
8524
|
+
className: cn(
|
|
8525
|
+
"cursor-pointer transition-colors",
|
|
8526
|
+
isSelected && "bg-green-50/50 dark:bg-green-950/20"
|
|
8527
|
+
),
|
|
8528
|
+
onClick: () => toggleElement(element.id),
|
|
8529
|
+
children: [
|
|
8530
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "w-[44px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8531
|
+
Checkbox,
|
|
8532
|
+
{
|
|
8533
|
+
checked: isSelected,
|
|
8534
|
+
onCheckedChange: () => toggleElement(element.id),
|
|
8535
|
+
onClick: (e) => e.stopPropagation(),
|
|
8536
|
+
"aria-label": `Mark ${element.name} as produced`
|
|
8537
|
+
}
|
|
8538
|
+
) }),
|
|
8539
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8540
|
+
element.prefix && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "text-[10px] h-5 shrink-0 font-mono", children: element.prefix }),
|
|
8541
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: element.name })
|
|
8542
|
+
] }) }),
|
|
8543
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-muted-foreground w-[80px]", children: element.type || "\u2014" }),
|
|
8544
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums text-muted-foreground w-[90px]", children: element.weight != null ? `${element.weight.toLocaleString()} kg` : "\u2014" }),
|
|
8545
|
+
/* @__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" }),
|
|
8546
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-center w-[100px]", children: isSelected ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8547
|
+
Badge,
|
|
8548
|
+
{
|
|
8549
|
+
variant: "outline",
|
|
8550
|
+
className: "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50",
|
|
8551
|
+
children: [
|
|
8552
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3 mr-1" }),
|
|
8553
|
+
"Produced"
|
|
8554
|
+
]
|
|
8555
|
+
}
|
|
8556
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8557
|
+
Badge,
|
|
8558
|
+
{
|
|
8559
|
+
variant: "outline",
|
|
8560
|
+
className: "border-muted-foreground/50 text-muted-foreground",
|
|
8561
|
+
children: "Not produced"
|
|
8562
|
+
}
|
|
8563
|
+
) })
|
|
8564
|
+
]
|
|
8565
|
+
},
|
|
8566
|
+
element.id
|
|
8567
|
+
);
|
|
8568
|
+
}) })
|
|
8569
|
+
] }) }) : /* @__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: [
|
|
8570
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-10 w-10 mx-auto mb-3 opacity-50" }),
|
|
8571
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "No elements found" }),
|
|
8572
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Try adjusting your search" })
|
|
8573
|
+
] }) }) })
|
|
8574
|
+
] }),
|
|
8575
|
+
/* @__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: [
|
|
8576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
8577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
8578
|
+
selectedCount,
|
|
8579
|
+
" / ",
|
|
8580
|
+
totalCount,
|
|
8581
|
+
" elements"
|
|
8582
|
+
] }),
|
|
8583
|
+
totalWeight > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8584
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2022" }),
|
|
8585
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums font-medium text-foreground", children: [
|
|
8586
|
+
(selectedWeight / 1e3).toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
8198
8587
|
" / ",
|
|
8199
|
-
|
|
8200
|
-
"
|
|
8588
|
+
(totalWeight / 1e3).toLocaleString(void 0, { maximumFractionDigits: 1 }),
|
|
8589
|
+
" ton"
|
|
8201
8590
|
] })
|
|
8202
8591
|
] })
|
|
8203
|
-
]
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
}
|
|
8592
|
+
] }),
|
|
8593
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
8594
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
8595
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleSave, children: "Save progress" })
|
|
8596
|
+
] })
|
|
8597
|
+
] }) })
|
|
8598
|
+
] }) });
|
|
8599
|
+
}
|
|
8600
|
+
function DeliveryCommentPopover2({
|
|
8601
|
+
comments = [],
|
|
8602
|
+
onAddComment,
|
|
8603
|
+
deliveryLabel
|
|
8604
|
+
}) {
|
|
8605
|
+
const [open, setOpen] = React29__namespace.useState(false);
|
|
8606
|
+
const [newCommentText, setNewCommentText] = React29__namespace.useState("");
|
|
8607
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React29__namespace.useState(true);
|
|
8608
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
8609
|
+
const handleSubmit = () => {
|
|
8610
|
+
if (newCommentText.trim() && onAddComment) {
|
|
8611
|
+
onAddComment(newCommentText.trim());
|
|
8612
|
+
setNewCommentText("");
|
|
8613
|
+
setShowAddForm(false);
|
|
8614
|
+
setViewCommentsOpen(true);
|
|
8615
|
+
}
|
|
8616
|
+
};
|
|
8617
|
+
const handleKeyDown = (e) => {
|
|
8618
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
8619
|
+
e.preventDefault();
|
|
8620
|
+
handleSubmit();
|
|
8621
|
+
}
|
|
8622
|
+
if (e.key === "Escape") {
|
|
8623
|
+
setShowAddForm(false);
|
|
8624
|
+
setNewCommentText("");
|
|
8625
|
+
}
|
|
8626
|
+
};
|
|
8627
|
+
const formatDate3 = (date) => {
|
|
8628
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
8629
|
+
month: "short",
|
|
8630
|
+
day: "numeric",
|
|
8631
|
+
hour: "numeric",
|
|
8632
|
+
minute: "2-digit"
|
|
8633
|
+
}).format(date);
|
|
8634
|
+
};
|
|
8635
|
+
React29__namespace.useEffect(() => {
|
|
8636
|
+
if (!open) {
|
|
8637
|
+
setShowAddForm(false);
|
|
8638
|
+
setNewCommentText("");
|
|
8639
|
+
}
|
|
8640
|
+
}, [open]);
|
|
8641
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
8642
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
8643
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8644
|
+
PopoverContent,
|
|
8645
|
+
{
|
|
8646
|
+
className: "w-80 p-0 z-[100]",
|
|
8647
|
+
align: "end",
|
|
8648
|
+
sideOffset: 8,
|
|
8649
|
+
collisionPadding: 16,
|
|
8650
|
+
children: [
|
|
8651
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
8652
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
8653
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: deliveryLabel })
|
|
8654
|
+
] }),
|
|
8655
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 space-y-2 h-fit overflow-y-auto", children: [
|
|
8656
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
8657
|
+
/* @__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: [
|
|
8658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium", children: [
|
|
8659
|
+
"Comments ",
|
|
8660
|
+
comments.length > 0 && `(${comments.length})`
|
|
8661
|
+
] }),
|
|
8662
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
|
|
8663
|
+
"h-4 w-4 transition-transform duration-200",
|
|
8664
|
+
viewCommentsOpen && "rotate-180"
|
|
8665
|
+
) })
|
|
8666
|
+
] }) }),
|
|
8667
|
+
/* @__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: [
|
|
8668
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8669
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
8670
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
8671
|
+
] }),
|
|
8672
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
8673
|
+
] }, comment.id)) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
8674
|
+
] }),
|
|
8675
|
+
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
8676
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8677
|
+
Button,
|
|
8678
|
+
{
|
|
8679
|
+
variant: "outline",
|
|
8680
|
+
size: "sm",
|
|
8681
|
+
className: "w-full justify-center gap-2 h-8",
|
|
8682
|
+
onClick: () => setShowAddForm(true),
|
|
8683
|
+
children: [
|
|
8684
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
8685
|
+
"Add comment"
|
|
8686
|
+
]
|
|
8687
|
+
}
|
|
8688
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
8689
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
8690
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
8691
|
+
), children: [
|
|
8692
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8693
|
+
Textarea,
|
|
8694
|
+
{
|
|
8695
|
+
placeholder: "Type your comment...",
|
|
8696
|
+
value: newCommentText,
|
|
8697
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
8698
|
+
onKeyDown: handleKeyDown,
|
|
8699
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
8700
|
+
autoFocus: true
|
|
8701
|
+
}
|
|
8702
|
+
),
|
|
8703
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8704
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
8705
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8706
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8707
|
+
Button,
|
|
8708
|
+
{
|
|
8709
|
+
variant: "ghost",
|
|
8710
|
+
size: "sm",
|
|
8711
|
+
className: "h-7",
|
|
8712
|
+
onClick: () => {
|
|
8713
|
+
setShowAddForm(false);
|
|
8714
|
+
setNewCommentText("");
|
|
8715
|
+
},
|
|
8716
|
+
children: "Cancel"
|
|
8717
|
+
}
|
|
8718
|
+
),
|
|
8719
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8720
|
+
Button,
|
|
8721
|
+
{
|
|
8722
|
+
size: "sm",
|
|
8723
|
+
className: "h-7 gap-1",
|
|
8724
|
+
onClick: handleSubmit,
|
|
8725
|
+
disabled: !newCommentText.trim(),
|
|
8726
|
+
children: [
|
|
8727
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
8728
|
+
"Save"
|
|
8729
|
+
]
|
|
8730
|
+
}
|
|
8731
|
+
)
|
|
8732
|
+
] })
|
|
8733
|
+
] })
|
|
8734
|
+
] })
|
|
8735
|
+
] })
|
|
8736
|
+
]
|
|
8737
|
+
}
|
|
8738
|
+
)
|
|
8739
|
+
] });
|
|
8740
|
+
}
|
|
8741
|
+
function ProductionCommentSection2({
|
|
8742
|
+
comments = [],
|
|
8743
|
+
onAddComment
|
|
8744
|
+
}) {
|
|
8745
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
8746
|
+
const [newComment, setNewComment] = React29__namespace.useState("");
|
|
8747
|
+
const handleSubmit = () => {
|
|
8748
|
+
if (newComment.trim() && onAddComment) {
|
|
8749
|
+
onAddComment(newComment.trim());
|
|
8750
|
+
setNewComment("");
|
|
8751
|
+
setShowAddForm(false);
|
|
8752
|
+
}
|
|
8753
|
+
};
|
|
8754
|
+
const handleKeyDown = (e) => {
|
|
8755
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
8756
|
+
e.preventDefault();
|
|
8757
|
+
handleSubmit();
|
|
8758
|
+
}
|
|
8759
|
+
if (e.key === "Escape") {
|
|
8760
|
+
setShowAddForm(false);
|
|
8761
|
+
setNewComment("");
|
|
8762
|
+
}
|
|
8763
|
+
};
|
|
8764
|
+
const formatDate3 = (date) => {
|
|
8765
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
8766
|
+
month: "short",
|
|
8767
|
+
day: "numeric",
|
|
8768
|
+
hour: "numeric",
|
|
8769
|
+
minute: "2-digit"
|
|
8770
|
+
}).format(date);
|
|
8771
|
+
};
|
|
8772
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
8773
|
+
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: [
|
|
8774
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8775
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
8776
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate3(comment.createdAt) })
|
|
8777
|
+
] }),
|
|
8778
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
8779
|
+
] }, comment.id)) }),
|
|
8780
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8781
|
+
Button,
|
|
8782
|
+
{
|
|
8783
|
+
variant: "ghost",
|
|
8784
|
+
size: "sm",
|
|
8785
|
+
className: "w-full justify-start gap-2 h-8 text-muted-foreground",
|
|
8786
|
+
onClick: () => setShowAddForm(true),
|
|
8787
|
+
children: [
|
|
8788
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5" }),
|
|
8789
|
+
comments.length > 0 ? "Add another comment" : "Add a comment..."
|
|
8790
|
+
]
|
|
8791
|
+
}
|
|
8792
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 animate-in fade-in-0 slide-in-from-top-2 duration-200", children: [
|
|
8793
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8794
|
+
Textarea,
|
|
8795
|
+
{
|
|
8796
|
+
placeholder: "Add a comment...",
|
|
8797
|
+
value: newComment,
|
|
8798
|
+
onChange: (e) => setNewComment(e.target.value),
|
|
8799
|
+
onKeyDown: handleKeyDown,
|
|
8800
|
+
className: "min-h-[60px] text-sm resize-none",
|
|
8801
|
+
autoFocus: true
|
|
8802
|
+
}
|
|
8803
|
+
),
|
|
8804
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8805
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send" }),
|
|
8806
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8807
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8808
|
+
Button,
|
|
8809
|
+
{
|
|
8810
|
+
variant: "ghost",
|
|
8811
|
+
size: "sm",
|
|
8812
|
+
className: "h-7",
|
|
8813
|
+
onClick: () => {
|
|
8814
|
+
setShowAddForm(false);
|
|
8815
|
+
setNewComment("");
|
|
8816
|
+
},
|
|
8817
|
+
children: "Cancel"
|
|
8818
|
+
}
|
|
8819
|
+
),
|
|
8820
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8821
|
+
Button,
|
|
8822
|
+
{
|
|
8823
|
+
size: "sm",
|
|
8824
|
+
className: "h-7 gap-1",
|
|
8825
|
+
onClick: handleSubmit,
|
|
8826
|
+
disabled: !newComment.trim(),
|
|
8827
|
+
children: [
|
|
8828
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
8829
|
+
"Save"
|
|
8830
|
+
]
|
|
8831
|
+
}
|
|
8832
|
+
)
|
|
8833
|
+
] })
|
|
8834
|
+
] })
|
|
8835
|
+
] })
|
|
8836
|
+
] });
|
|
8837
|
+
}
|
|
8838
|
+
function DeliveryListItem2({
|
|
8839
|
+
delivery,
|
|
8840
|
+
index,
|
|
8841
|
+
onClick
|
|
8842
|
+
}) {
|
|
8843
|
+
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
8844
|
+
const isComplete = (delivery.progress ?? 0) >= 100;
|
|
8845
|
+
const getIconStyles = () => {
|
|
8846
|
+
if (delivery.status === "critical") {
|
|
8847
|
+
return { bg: "bg-red-100 dark:bg-red-950/50", icon: "text-red-600 dark:text-red-400" };
|
|
8848
|
+
}
|
|
8849
|
+
if (delivery.status === "delayed") {
|
|
8850
|
+
return { bg: "bg-amber-100 dark:bg-amber-950/50", icon: "text-amber-600 dark:text-amber-400" };
|
|
8851
|
+
}
|
|
8852
|
+
if (isComplete) {
|
|
8853
|
+
return { bg: "bg-green-100 dark:bg-green-950/50", icon: "text-green-600 dark:text-green-400" };
|
|
8854
|
+
}
|
|
8855
|
+
return { bg: "bg-muted", icon: "text-muted-foreground" };
|
|
8856
|
+
};
|
|
8857
|
+
const iconStyles = getIconStyles();
|
|
8858
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8859
|
+
"button",
|
|
8860
|
+
{
|
|
8861
|
+
onClick,
|
|
8862
|
+
className: cn(
|
|
8863
|
+
"w-full flex items-center justify-between p-3 rounded-lg",
|
|
8864
|
+
"bg-card border hover:bg-muted/50 transition-colors cursor-pointer",
|
|
8865
|
+
"text-left"
|
|
8866
|
+
),
|
|
8867
|
+
children: [
|
|
8868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
8869
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
8870
|
+
"flex items-center justify-center h-8 w-8 rounded-lg",
|
|
8871
|
+
iconStyles.bg
|
|
8872
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-4 w-4", iconStyles.icon) }) }),
|
|
8873
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8874
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8875
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: delivery.label || `Delivery ${index + 1}` }),
|
|
8876
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8877
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3 w-3 text-muted-foreground" }),
|
|
8878
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-primary" })
|
|
8879
|
+
] })
|
|
8880
|
+
] }),
|
|
8881
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
8882
|
+
"\u2192 ",
|
|
8883
|
+
delivery.destination
|
|
8884
|
+
] })
|
|
8885
|
+
] })
|
|
8886
|
+
] }),
|
|
8887
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8888
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8889
|
+
Badge,
|
|
8890
|
+
{
|
|
8891
|
+
variant: getStatusBadgeVariant2(delivery.status, isComplete),
|
|
8892
|
+
className: cn("text-xs", getStatusBadgeClasses2(delivery.status, isComplete)),
|
|
8893
|
+
children: getStatusLabel2(delivery.status, isComplete)
|
|
8894
|
+
}
|
|
8895
|
+
),
|
|
8896
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
8897
|
+
] })
|
|
8898
|
+
]
|
|
8899
|
+
}
|
|
8900
|
+
);
|
|
8901
|
+
}
|
|
8902
|
+
function DeliveryDetailsView2({
|
|
8903
|
+
delivery,
|
|
8904
|
+
week,
|
|
8905
|
+
onBack,
|
|
8906
|
+
onAddComment
|
|
8907
|
+
}) {
|
|
8908
|
+
const elements = delivery.elements ?? [];
|
|
8909
|
+
const categorizedElements = React29__namespace.useMemo(() => {
|
|
8910
|
+
const sent = [];
|
|
8911
|
+
const notSent = [];
|
|
8912
|
+
const moved = [];
|
|
8913
|
+
const addons = [];
|
|
8914
|
+
elements.forEach((element) => {
|
|
8915
|
+
const status = getElementShipmentStatus(element, delivery.id);
|
|
8916
|
+
switch (status) {
|
|
8917
|
+
case "sent":
|
|
8918
|
+
sent.push(element);
|
|
8919
|
+
break;
|
|
8920
|
+
case "not-sent":
|
|
8921
|
+
notSent.push(element);
|
|
8922
|
+
break;
|
|
8923
|
+
case "moved":
|
|
8924
|
+
moved.push(element);
|
|
8925
|
+
break;
|
|
8926
|
+
case "addon":
|
|
8927
|
+
addons.push(element);
|
|
8928
|
+
break;
|
|
8929
|
+
default:
|
|
8930
|
+
notSent.push(element);
|
|
8931
|
+
}
|
|
8932
|
+
});
|
|
8933
|
+
return { sent, notSent, moved, addons };
|
|
8934
|
+
}, [elements, delivery.id]);
|
|
8935
|
+
const totalCount = elements.length;
|
|
8936
|
+
const sentCount = categorizedElements.sent.length;
|
|
8937
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full animate-in slide-in-from-right-4 duration-200", children: [
|
|
8938
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-4 py-3 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8939
|
+
Button,
|
|
8940
|
+
{
|
|
8941
|
+
variant: "ghost",
|
|
8942
|
+
size: "sm",
|
|
8943
|
+
className: "gap-1 -ml-2",
|
|
8944
|
+
onClick: onBack,
|
|
8945
|
+
children: [
|
|
8946
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }),
|
|
8947
|
+
"Back"
|
|
8948
|
+
]
|
|
8949
|
+
}
|
|
8950
|
+
) }),
|
|
8951
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-4 space-y-2", children: [
|
|
8952
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8953
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: delivery.label || "Delivery Details" }),
|
|
8954
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8955
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8956
|
+
DeliveryCommentPopover2,
|
|
8957
|
+
{
|
|
8958
|
+
comments: delivery.comments,
|
|
8959
|
+
onAddComment,
|
|
8960
|
+
deliveryLabel: delivery.label || "Delivery"
|
|
8961
|
+
}
|
|
8962
|
+
),
|
|
8963
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8964
|
+
Badge,
|
|
8965
|
+
{
|
|
8966
|
+
variant: getStatusBadgeVariant2(delivery.status, sentCount === totalCount && totalCount > 0),
|
|
8967
|
+
className: cn("text-xs", getStatusBadgeClasses2(delivery.status, sentCount === totalCount && totalCount > 0)),
|
|
8968
|
+
children: getStatusLabel2(delivery.status, sentCount === totalCount && totalCount > 0)
|
|
8969
|
+
}
|
|
8970
|
+
)
|
|
8971
|
+
] })
|
|
8972
|
+
] }),
|
|
8973
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
8974
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
8975
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-3.5 w-3.5" }),
|
|
8976
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
8977
|
+
week.label,
|
|
8978
|
+
" \u2022 ",
|
|
8979
|
+
week.dateRange
|
|
8980
|
+
] })
|
|
8981
|
+
] }),
|
|
8982
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
8983
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3.5 w-3.5" }),
|
|
8984
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
8985
|
+
"\u2192 ",
|
|
8986
|
+
delivery.destination
|
|
8987
|
+
] })
|
|
8988
|
+
] })
|
|
8989
|
+
] })
|
|
8990
|
+
] }),
|
|
8991
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-4 pb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
8992
|
+
totalCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-4 space-y-3", children: [
|
|
8993
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8994
|
+
StatusProgress,
|
|
8995
|
+
{
|
|
8996
|
+
value: totalCount > 0 ? sentCount / totalCount * 100 : 0,
|
|
8997
|
+
currentCount: sentCount,
|
|
8998
|
+
totalCount,
|
|
8999
|
+
unitLabel: "shipped",
|
|
9000
|
+
showLabel: true,
|
|
9001
|
+
showCheckmark: true,
|
|
9002
|
+
size: "md"
|
|
9003
|
+
}
|
|
9004
|
+
),
|
|
9005
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap", children: [
|
|
9006
|
+
categorizedElements.sent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9007
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-3 w-3 text-green-600" }),
|
|
9008
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-green-700 dark:text-green-300", children: [
|
|
9009
|
+
categorizedElements.sent.length,
|
|
9010
|
+
" Sent"
|
|
9011
|
+
] })
|
|
9012
|
+
] }),
|
|
9013
|
+
categorizedElements.notSent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9014
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-3 w-3 text-muted-foreground" }),
|
|
9015
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
9016
|
+
categorizedElements.notSent.length,
|
|
9017
|
+
" Missing"
|
|
9018
|
+
] })
|
|
9019
|
+
] }),
|
|
9020
|
+
categorizedElements.moved.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9021
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-3 w-3 text-blue-600" }),
|
|
9022
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-blue-700 dark:text-blue-300", children: [
|
|
9023
|
+
categorizedElements.moved.length,
|
|
9024
|
+
" Moved"
|
|
9025
|
+
] })
|
|
9026
|
+
] }),
|
|
9027
|
+
categorizedElements.addons.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
9028
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3 text-purple-600" }),
|
|
9029
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-700 dark:text-purple-300", children: [
|
|
9030
|
+
categorizedElements.addons.length,
|
|
9031
|
+
" Add-on"
|
|
9032
|
+
] })
|
|
9033
|
+
] })
|
|
9034
|
+
] })
|
|
9035
|
+
] }),
|
|
9036
|
+
elements.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
9037
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Elements" }),
|
|
9038
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
9039
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "bg-sidebar hover:bg-sidebar", children: [
|
|
9040
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Prefix" }),
|
|
9041
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Type" }),
|
|
9042
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-right", children: "Weight" }),
|
|
9043
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-center", children: "Status" })
|
|
9044
|
+
] }) }),
|
|
9045
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: elements.map((element) => {
|
|
9046
|
+
const shipmentStatus = getElementShipmentStatus(element, delivery.id);
|
|
9047
|
+
const statusLabel = getShipmentStatusLabel(shipmentStatus);
|
|
9048
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9049
|
+
TableRow,
|
|
9050
|
+
{
|
|
9051
|
+
className: getShipmentStatusRowBg2(shipmentStatus),
|
|
9052
|
+
children: [
|
|
9053
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "font-medium", children: element.prefix || "\u2014" }),
|
|
9054
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: element.type || element.name || "\u2014" }),
|
|
9055
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums", children: element.weight ? `${element.weight} ${element.weightUnit || "kg"}` : "\u2014" }),
|
|
9056
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
9057
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9058
|
+
Badge,
|
|
9059
|
+
{
|
|
9060
|
+
variant: "outline",
|
|
9061
|
+
className: cn("text-[10px] h-5", getShipmentStatusBadgeClasses2(shipmentStatus)),
|
|
9062
|
+
children: statusLabel
|
|
9063
|
+
}
|
|
9064
|
+
),
|
|
9065
|
+
shipmentStatus === "moved" && element.actualDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-blue-600 dark:text-blue-400", children: [
|
|
9066
|
+
"\u2192 ",
|
|
9067
|
+
element.actualDeliveryLabel
|
|
9068
|
+
] }),
|
|
9069
|
+
shipmentStatus === "addon" && element.originalDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-purple-600 dark:text-purple-400", children: [
|
|
9070
|
+
"from ",
|
|
9071
|
+
element.originalDeliveryLabel
|
|
9072
|
+
] })
|
|
9073
|
+
] }) })
|
|
9074
|
+
]
|
|
9075
|
+
},
|
|
9076
|
+
element.id
|
|
9077
|
+
);
|
|
9078
|
+
}) })
|
|
9079
|
+
] }) })
|
|
9080
|
+
] }),
|
|
9081
|
+
elements.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
9082
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
9083
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No elements in this delivery" })
|
|
9084
|
+
] })
|
|
9085
|
+
] }) })
|
|
9086
|
+
] });
|
|
9087
|
+
}
|
|
9088
|
+
function MainView2({
|
|
9089
|
+
supplier,
|
|
9090
|
+
week,
|
|
9091
|
+
data,
|
|
9092
|
+
productionElements,
|
|
9093
|
+
previousProducedCount,
|
|
9094
|
+
onOpenProductionDialog,
|
|
9095
|
+
onSelectDelivery,
|
|
9096
|
+
onAddProductionComment
|
|
9097
|
+
}) {
|
|
9098
|
+
const production = data?.production;
|
|
9099
|
+
const producedCount = productionElements.filter((e) => e.isProduced).length;
|
|
9100
|
+
const totalCount = productionElements.length;
|
|
9101
|
+
const productionProgress = totalCount > 0 ? Math.round(producedCount / totalCount * 100) : 0;
|
|
9102
|
+
const isComplete = productionProgress >= 100;
|
|
9103
|
+
const hasProductionComments = (production?.comments?.length ?? 0) > 0;
|
|
9104
|
+
const showPreviousProgress = !isComplete && previousProducedCount !== void 0 && previousProducedCount !== producedCount;
|
|
9105
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-in fade-in-0 duration-200", children: [
|
|
9106
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetHeader, { className: "px-4 pt-4 pb-3 border-b", children: [
|
|
9107
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetTitle, { className: "flex items-center gap-2", children: [
|
|
9108
|
+
supplier.name,
|
|
9109
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs font-normal", children: supplier.badgeType })
|
|
9110
|
+
] }),
|
|
9111
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SheetDescription, { className: "flex items-center gap-2", children: [
|
|
9112
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-4 w-4" }),
|
|
9113
|
+
week.label,
|
|
9114
|
+
" \u2022 ",
|
|
9115
|
+
week.dateRange
|
|
9116
|
+
] })
|
|
9117
|
+
] }),
|
|
9118
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-4 pb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pt-4", children: [
|
|
9119
|
+
data.type !== "empty" && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
9120
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9121
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-4 w-4 text-muted-foreground" }),
|
|
9122
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Production" })
|
|
9123
|
+
] }),
|
|
9124
|
+
totalCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
9125
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center py-4", children: [
|
|
9126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9127
|
+
CircularProgress,
|
|
9128
|
+
{
|
|
9129
|
+
value: productionProgress,
|
|
9130
|
+
size: 88,
|
|
9131
|
+
strokeWidth: 8,
|
|
9132
|
+
variant: productionProgress >= 100 ? "success" : productionProgress >= 50 ? "success" : productionProgress > 0 ? "warning" : "destructive",
|
|
9133
|
+
showCheckmark: true,
|
|
9134
|
+
children: productionProgress < 100 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold tabular-nums", children: [
|
|
9135
|
+
Math.round(productionProgress),
|
|
9136
|
+
"%"
|
|
9137
|
+
] })
|
|
9138
|
+
}
|
|
9139
|
+
),
|
|
9140
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 text-center", children: [
|
|
9141
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold text-foreground", children: [
|
|
9142
|
+
producedCount,
|
|
9143
|
+
" / ",
|
|
9144
|
+
totalCount,
|
|
9145
|
+
" elements"
|
|
9146
|
+
] }),
|
|
9147
|
+
showPreviousProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
9148
|
+
"Previously: ",
|
|
9149
|
+
previousProducedCount,
|
|
9150
|
+
" / ",
|
|
9151
|
+
totalCount
|
|
9152
|
+
] })
|
|
9153
|
+
] })
|
|
9154
|
+
] }),
|
|
9155
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9156
|
+
Button,
|
|
9157
|
+
{
|
|
9158
|
+
className: "w-full",
|
|
9159
|
+
onClick: onOpenProductionDialog,
|
|
9160
|
+
children: "Enter production progress"
|
|
9161
|
+
}
|
|
9162
|
+
)
|
|
9163
|
+
] }) : (
|
|
9164
|
+
/* No elements - show placeholder with button still available */
|
|
9165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
9166
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-6 text-muted-foreground bg-muted/30 rounded-lg", children: [
|
|
9167
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
9168
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No elements to track" })
|
|
9169
|
+
] }),
|
|
9170
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9171
|
+
Button,
|
|
9172
|
+
{
|
|
9173
|
+
className: "w-full",
|
|
9174
|
+
variant: "outline",
|
|
9175
|
+
onClick: onOpenProductionDialog,
|
|
9176
|
+
children: "Enter production progress"
|
|
9177
|
+
}
|
|
9178
|
+
)
|
|
9179
|
+
] })
|
|
9180
|
+
),
|
|
9181
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9182
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Comments" }),
|
|
9184
|
+
hasProductionComments && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
9185
|
+
"(",
|
|
9186
|
+
production?.comments?.length,
|
|
9187
|
+
")"
|
|
9188
|
+
] })
|
|
9189
|
+
] }),
|
|
9190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9191
|
+
ProductionCommentSection2,
|
|
9192
|
+
{
|
|
9193
|
+
comments: production?.comments,
|
|
9194
|
+
onAddComment: onAddProductionComment
|
|
9195
|
+
}
|
|
9196
|
+
)
|
|
9197
|
+
] })
|
|
9198
|
+
] }),
|
|
9199
|
+
data.deliveries && data.deliveries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
9200
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
9201
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4 text-muted-foreground" }),
|
|
9202
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Deliveries" }),
|
|
9203
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground ml-auto", children: [
|
|
9204
|
+
data.deliveries.length,
|
|
9205
|
+
" scheduled"
|
|
9206
|
+
] })
|
|
9207
|
+
] }),
|
|
9208
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: data.deliveries.map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9209
|
+
DeliveryListItem2,
|
|
9210
|
+
{
|
|
9211
|
+
delivery,
|
|
9212
|
+
index,
|
|
9213
|
+
onClick: () => onSelectDelivery(delivery)
|
|
9214
|
+
},
|
|
9215
|
+
delivery.id
|
|
9216
|
+
)) })
|
|
9217
|
+
] }),
|
|
9218
|
+
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: [
|
|
9219
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4" }),
|
|
9220
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "No logistics scheduled for this week" })
|
|
9221
|
+
] }),
|
|
9222
|
+
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: [
|
|
9223
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }),
|
|
9224
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm", children: data.warningMessage })
|
|
9225
|
+
] }),
|
|
9226
|
+
data.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
9227
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Notes" }),
|
|
9228
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: data.notes })
|
|
9229
|
+
] })
|
|
9230
|
+
] }) })
|
|
9231
|
+
] });
|
|
9232
|
+
}
|
|
9233
|
+
function WeekDetailSheet({
|
|
9234
|
+
open,
|
|
9235
|
+
onOpenChange,
|
|
9236
|
+
supplier,
|
|
9237
|
+
week,
|
|
9238
|
+
data,
|
|
9239
|
+
onProductionUpdate,
|
|
9240
|
+
onAddProductionComment,
|
|
9241
|
+
onAddDeliveryComment
|
|
9242
|
+
}) {
|
|
9243
|
+
const [selectedDelivery, setSelectedDelivery] = React29__namespace.useState(null);
|
|
9244
|
+
const [productionDialogOpen, setProductionDialogOpen] = React29__namespace.useState(false);
|
|
9245
|
+
const [previousProducedCount, setPreviousProducedCount] = React29__namespace.useState(void 0);
|
|
9246
|
+
const productionElements = React29__namespace.useMemo(() => {
|
|
9247
|
+
if (!data?.deliveries) return [];
|
|
9248
|
+
const elements = [];
|
|
9249
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
9250
|
+
data.deliveries.forEach((delivery) => {
|
|
9251
|
+
delivery.elements?.forEach((element) => {
|
|
9252
|
+
if (!seenIds.has(element.id)) {
|
|
9253
|
+
seenIds.add(element.id);
|
|
9254
|
+
elements.push({
|
|
9255
|
+
id: element.id,
|
|
9256
|
+
name: element.name,
|
|
9257
|
+
prefix: element.prefix,
|
|
9258
|
+
type: element.type,
|
|
9259
|
+
weight: element.weight,
|
|
9260
|
+
size: element.sizeSqm,
|
|
9261
|
+
sizeUnit: "sqm",
|
|
9262
|
+
isProduced: element.isProduced
|
|
9263
|
+
});
|
|
9264
|
+
}
|
|
9265
|
+
});
|
|
9266
|
+
});
|
|
9267
|
+
return elements;
|
|
9268
|
+
}, [data?.deliveries]);
|
|
9269
|
+
const currentProducedCount = productionElements.filter((e) => e.isProduced).length;
|
|
9270
|
+
React29__namespace.useEffect(() => {
|
|
9271
|
+
if (open && data?.deliveries) {
|
|
9272
|
+
setPreviousProducedCount(currentProducedCount);
|
|
9273
|
+
}
|
|
9274
|
+
}, [open]);
|
|
9275
|
+
React29__namespace.useEffect(() => {
|
|
9276
|
+
if (!open) {
|
|
9277
|
+
setSelectedDelivery(null);
|
|
9278
|
+
setProductionDialogOpen(false);
|
|
9279
|
+
setPreviousProducedCount(void 0);
|
|
9280
|
+
}
|
|
9281
|
+
}, [open]);
|
|
9282
|
+
const handleProductionSave = (producedIds) => {
|
|
9283
|
+
if (!supplier || !week || !onProductionUpdate) return;
|
|
9284
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9285
|
+
onProductionUpdate(supplier.id, weekKey, producedIds);
|
|
9286
|
+
setPreviousProducedCount(producedIds.length);
|
|
9287
|
+
};
|
|
9288
|
+
if (!supplier || !week || !data) {
|
|
9289
|
+
return null;
|
|
9290
|
+
}
|
|
9291
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9292
|
+
/* @__PURE__ */ jsxRuntime.jsx(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9293
|
+
SheetContent,
|
|
9294
|
+
{
|
|
9295
|
+
side: "right",
|
|
9296
|
+
className: "w-full sm:max-w-lg p-0 overflow-hidden",
|
|
9297
|
+
children: selectedDelivery ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9298
|
+
DeliveryDetailsView2,
|
|
9299
|
+
{
|
|
9300
|
+
delivery: selectedDelivery,
|
|
9301
|
+
week,
|
|
9302
|
+
onBack: () => setSelectedDelivery(null),
|
|
9303
|
+
onAddComment: onAddDeliveryComment ? (text) => {
|
|
9304
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9305
|
+
onAddDeliveryComment(supplier.id, weekKey, selectedDelivery.id, text);
|
|
9306
|
+
} : void 0
|
|
9307
|
+
}
|
|
9308
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9309
|
+
MainView2,
|
|
9310
|
+
{
|
|
9311
|
+
supplier,
|
|
9312
|
+
week,
|
|
9313
|
+
data,
|
|
9314
|
+
productionElements,
|
|
9315
|
+
previousProducedCount,
|
|
9316
|
+
onOpenProductionDialog: () => setProductionDialogOpen(true),
|
|
9317
|
+
onSelectDelivery: setSelectedDelivery,
|
|
9318
|
+
onAddProductionComment: onAddProductionComment ? (text) => {
|
|
9319
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
9320
|
+
onAddProductionComment(supplier.id, weekKey, text);
|
|
9321
|
+
} : void 0
|
|
9322
|
+
}
|
|
9323
|
+
)
|
|
9324
|
+
}
|
|
9325
|
+
) }),
|
|
9326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9327
|
+
ElementProductionDialog,
|
|
9328
|
+
{
|
|
9329
|
+
open: productionDialogOpen,
|
|
9330
|
+
onOpenChange: setProductionDialogOpen,
|
|
9331
|
+
elements: productionElements,
|
|
9332
|
+
onSave: handleProductionSave
|
|
9333
|
+
}
|
|
9334
|
+
)
|
|
9335
|
+
] });
|
|
9336
|
+
}
|
|
9337
|
+
function RowHeaderCell({
|
|
9338
|
+
className,
|
|
9339
|
+
data,
|
|
9340
|
+
showProgress = true,
|
|
9341
|
+
...props
|
|
9342
|
+
}) {
|
|
9343
|
+
const progressPercent = data.totalRequired > 0 ? Math.min(data.totalBooked / data.totalRequired * 100, 100) : 0;
|
|
9344
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9345
|
+
"div",
|
|
9346
|
+
{
|
|
9347
|
+
"data-slot": "row-header-cell",
|
|
9348
|
+
className: cn(
|
|
9349
|
+
"flex flex-col justify-center gap-1.5 py-2 px-3 min-w-[200px] h-[100px] bg-background",
|
|
9350
|
+
className
|
|
9351
|
+
),
|
|
9352
|
+
...props,
|
|
9353
|
+
children: [
|
|
9354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
9355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
9356
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: data.name }),
|
|
9357
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: data.typeCode })
|
|
9358
|
+
] }),
|
|
9359
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9360
|
+
Badge,
|
|
9361
|
+
{
|
|
9362
|
+
variant: "outline",
|
|
9363
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
9364
|
+
children: [
|
|
9365
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Flag, { className: "h-2.5 w-2.5" }),
|
|
9366
|
+
"Paint"
|
|
9367
|
+
]
|
|
9368
|
+
}
|
|
9369
|
+
)
|
|
9370
|
+
] }),
|
|
9371
|
+
showProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
9372
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9373
|
+
"div",
|
|
9374
|
+
{
|
|
9375
|
+
className: "h-full bg-primary rounded-full transition-all",
|
|
9376
|
+
style: { width: `${progressPercent}%` }
|
|
9377
|
+
}
|
|
9378
|
+
) }),
|
|
9379
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-primary", children: [
|
|
9380
|
+
data.totalBooked.toLocaleString(),
|
|
9381
|
+
" / ",
|
|
9382
|
+
data.totalRequired.toLocaleString(),
|
|
9383
|
+
" Booked"
|
|
9384
|
+
] })
|
|
9385
|
+
] })
|
|
9386
|
+
]
|
|
9387
|
+
}
|
|
9388
|
+
);
|
|
9389
|
+
}
|
|
8207
9390
|
function NetBadge({
|
|
8208
9391
|
className,
|
|
8209
9392
|
net,
|
|
@@ -8322,13 +9505,13 @@ function CalibrationWeekCell({
|
|
|
8322
9505
|
onAddClick,
|
|
8323
9506
|
...props
|
|
8324
9507
|
}) {
|
|
8325
|
-
const inputRef =
|
|
8326
|
-
const [localValue, setLocalValue] =
|
|
9508
|
+
const inputRef = React29__namespace.useRef(null);
|
|
9509
|
+
const [localValue, setLocalValue] = React29__namespace.useState(
|
|
8327
9510
|
data.entered !== null ? String(data.entered) : ""
|
|
8328
9511
|
);
|
|
8329
|
-
const [isHovered, setIsHovered] =
|
|
8330
|
-
const [isEditing, setIsEditing] =
|
|
8331
|
-
|
|
9512
|
+
const [isHovered, setIsHovered] = React29__namespace.useState(false);
|
|
9513
|
+
const [isEditing, setIsEditing] = React29__namespace.useState(false);
|
|
9514
|
+
React29__namespace.useEffect(() => {
|
|
8332
9515
|
setLocalValue(data.entered !== null ? String(data.entered) : "");
|
|
8333
9516
|
}, [data.entered]);
|
|
8334
9517
|
const unitLabel = formatCalibrationUnit(unit);
|
|
@@ -8514,11 +9697,11 @@ function CommentPopover({
|
|
|
8514
9697
|
open,
|
|
8515
9698
|
onOpenChange
|
|
8516
9699
|
}) {
|
|
8517
|
-
const [newCommentText, setNewCommentText] =
|
|
8518
|
-
const [selectedPrefixId, setSelectedPrefixId] =
|
|
8519
|
-
const [viewCommentsOpen, setViewCommentsOpen] =
|
|
8520
|
-
const [showAddForm, setShowAddForm] =
|
|
8521
|
-
const selectedPrefixName =
|
|
9700
|
+
const [newCommentText, setNewCommentText] = React29__namespace.useState("");
|
|
9701
|
+
const [selectedPrefixId, setSelectedPrefixId] = React29__namespace.useState("");
|
|
9702
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React29__namespace.useState(true);
|
|
9703
|
+
const [showAddForm, setShowAddForm] = React29__namespace.useState(false);
|
|
9704
|
+
const selectedPrefixName = React29__namespace.useMemo(() => {
|
|
8522
9705
|
const prefix = availablePrefixes.find((p) => p.id === selectedPrefixId);
|
|
8523
9706
|
return prefix?.name ?? "";
|
|
8524
9707
|
}, [availablePrefixes, selectedPrefixId]);
|
|
@@ -8550,8 +9733,8 @@ function CommentPopover({
|
|
|
8550
9733
|
minute: "2-digit"
|
|
8551
9734
|
}).format(date);
|
|
8552
9735
|
};
|
|
8553
|
-
const prevOpenRef =
|
|
8554
|
-
|
|
9736
|
+
const prevOpenRef = React29__namespace.useRef(open);
|
|
9737
|
+
React29__namespace.useEffect(() => {
|
|
8555
9738
|
const wasOpen = prevOpenRef.current;
|
|
8556
9739
|
prevOpenRef.current = open;
|
|
8557
9740
|
if (wasOpen && !open) {
|
|
@@ -8780,7 +9963,7 @@ function CalibrationTable({
|
|
|
8780
9963
|
onAddComment,
|
|
8781
9964
|
onAddEarlierWeek
|
|
8782
9965
|
} = config;
|
|
8783
|
-
const calculatedStartDate =
|
|
9966
|
+
const calculatedStartDate = React29__namespace.useMemo(() => {
|
|
8784
9967
|
if (startDate) return startDate;
|
|
8785
9968
|
let earliest = null;
|
|
8786
9969
|
for (const prefix of prefixes) {
|
|
@@ -8801,31 +9984,31 @@ function CalibrationTable({
|
|
|
8801
9984
|
}
|
|
8802
9985
|
return earliest ?? /* @__PURE__ */ new Date();
|
|
8803
9986
|
}, [startDate, prefixes]);
|
|
8804
|
-
const [additionalWeeks, setAdditionalWeeks] =
|
|
8805
|
-
const weeks =
|
|
9987
|
+
const [additionalWeeks, setAdditionalWeeks] = React29__namespace.useState(0);
|
|
9988
|
+
const weeks = React29__namespace.useMemo(() => {
|
|
8806
9989
|
const start = new Date(calculatedStartDate);
|
|
8807
9990
|
start.setDate(start.getDate() - additionalWeeks * 7);
|
|
8808
9991
|
return generateWeeks(start, weekCount + additionalWeeks);
|
|
8809
9992
|
}, [calculatedStartDate, weekCount, additionalWeeks]);
|
|
8810
|
-
|
|
9993
|
+
React29__namespace.useMemo(() => {
|
|
8811
9994
|
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
8812
9995
|
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
8813
9996
|
}, [weeks]);
|
|
8814
|
-
const [currentPage, setCurrentPage] =
|
|
8815
|
-
const [pageSize, setPageSize] =
|
|
8816
|
-
const [searchQuery, setSearchQuery] =
|
|
8817
|
-
const filteredPrefixes =
|
|
9997
|
+
const [currentPage, setCurrentPage] = React29__namespace.useState(0);
|
|
9998
|
+
const [pageSize, setPageSize] = React29__namespace.useState(defaultPageSize);
|
|
9999
|
+
const [searchQuery, setSearchQuery] = React29__namespace.useState("");
|
|
10000
|
+
const filteredPrefixes = React29__namespace.useMemo(() => {
|
|
8818
10001
|
if (!searchQuery) return prefixes;
|
|
8819
10002
|
const query = searchQuery.toLowerCase();
|
|
8820
10003
|
return prefixes.filter(
|
|
8821
10004
|
(p) => p.name.toLowerCase().includes(query) || p.typeCode.toLowerCase().includes(query)
|
|
8822
10005
|
);
|
|
8823
10006
|
}, [prefixes, searchQuery]);
|
|
8824
|
-
const paginatedPrefixes =
|
|
10007
|
+
const paginatedPrefixes = React29__namespace.useMemo(() => {
|
|
8825
10008
|
const start = currentPage * pageSize;
|
|
8826
10009
|
return filteredPrefixes.slice(start, start + pageSize);
|
|
8827
10010
|
}, [filteredPrefixes, currentPage, pageSize]);
|
|
8828
|
-
|
|
10011
|
+
React29__namespace.useMemo(
|
|
8829
10012
|
() => canSubmitCalibration(prefixes),
|
|
8830
10013
|
[prefixes]
|
|
8831
10014
|
);
|
|
@@ -8849,7 +10032,7 @@ function CalibrationTable({
|
|
|
8849
10032
|
}
|
|
8850
10033
|
return allComments;
|
|
8851
10034
|
};
|
|
8852
|
-
const availablePrefixes =
|
|
10035
|
+
const availablePrefixes = React29__namespace.useMemo(
|
|
8853
10036
|
() => prefixes.map((p) => ({ id: p.id, name: p.name })),
|
|
8854
10037
|
[prefixes]
|
|
8855
10038
|
);
|
|
@@ -9086,14 +10269,14 @@ function CommentDialog({
|
|
|
9086
10269
|
open,
|
|
9087
10270
|
onOpenChange
|
|
9088
10271
|
}) {
|
|
9089
|
-
const [selectedPrefixId, setSelectedPrefixId] =
|
|
9090
|
-
const [selectedWeekKey, setSelectedWeekKey] =
|
|
9091
|
-
const [commentText, setCommentText] =
|
|
9092
|
-
const currentWeek =
|
|
10272
|
+
const [selectedPrefixId, setSelectedPrefixId] = React29__namespace.useState("");
|
|
10273
|
+
const [selectedWeekKey, setSelectedWeekKey] = React29__namespace.useState("");
|
|
10274
|
+
const [commentText, setCommentText] = React29__namespace.useState("");
|
|
10275
|
+
const currentWeek = React29__namespace.useMemo(
|
|
9093
10276
|
() => weeks.find((w) => w.isCurrentWeek),
|
|
9094
10277
|
[weeks]
|
|
9095
10278
|
);
|
|
9096
|
-
|
|
10279
|
+
React29__namespace.useEffect(() => {
|
|
9097
10280
|
if (open) {
|
|
9098
10281
|
setSelectedPrefixId(prefixes[0]?.id ?? "");
|
|
9099
10282
|
setSelectedWeekKey(currentWeek ? getWeekKey(currentWeek.startDate) : weeks[0] ? getWeekKey(weeks[0].startDate) : "");
|
|
@@ -9423,40 +10606,36 @@ function groupDeliveriesByPrefixAndDay(deliveries) {
|
|
|
9423
10606
|
}
|
|
9424
10607
|
return grouped;
|
|
9425
10608
|
}
|
|
9426
|
-
function
|
|
10609
|
+
function getCardStyles(state, hasRisk, isHovered) {
|
|
9427
10610
|
if (hasRisk) {
|
|
9428
10611
|
return {
|
|
9429
10612
|
stroke: "border-l-[3px] border-l-red-500",
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
cardBg: "bg-background"
|
|
10613
|
+
cardBg: "bg-background",
|
|
10614
|
+
titleColor: "text-foreground",
|
|
10615
|
+
opacity: ""
|
|
9434
10616
|
};
|
|
9435
10617
|
}
|
|
9436
10618
|
switch (state) {
|
|
9437
10619
|
case "sent":
|
|
9438
10620
|
return {
|
|
9439
10621
|
stroke: "border-l-[3px] border-l-green-500/40",
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
cardBg: "bg-muted/30"
|
|
10622
|
+
cardBg: "bg-muted/40",
|
|
10623
|
+
titleColor: "text-muted-foreground",
|
|
10624
|
+
opacity: "opacity-60"
|
|
9444
10625
|
};
|
|
9445
10626
|
case "ready":
|
|
9446
10627
|
return {
|
|
9447
|
-
stroke: "border-l-[
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
cardBg: "bg-background"
|
|
10628
|
+
stroke: "border-l-[4px] border-l-green-500",
|
|
10629
|
+
cardBg: "bg-background",
|
|
10630
|
+
titleColor: "text-foreground",
|
|
10631
|
+
opacity: ""
|
|
9452
10632
|
};
|
|
9453
10633
|
default:
|
|
9454
10634
|
return {
|
|
9455
10635
|
stroke: isHovered ? "border-l-[3px] border-l-primary/50" : "border-l-[3px] border-l-border",
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
cardBg: "bg-background"
|
|
10636
|
+
cardBg: "bg-background",
|
|
10637
|
+
titleColor: "text-foreground",
|
|
10638
|
+
opacity: ""
|
|
9460
10639
|
};
|
|
9461
10640
|
}
|
|
9462
10641
|
}
|
|
@@ -9466,55 +10645,11 @@ function DeliveryBadge({
|
|
|
9466
10645
|
onCommentClick,
|
|
9467
10646
|
className
|
|
9468
10647
|
}) {
|
|
9469
|
-
const [isHovered, setIsHovered] =
|
|
10648
|
+
const [isHovered, setIsHovered] = React29__namespace.useState(false);
|
|
9470
10649
|
const hasComments = delivery.comments.length > 0;
|
|
9471
10650
|
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]);
|
|
10651
|
+
const styles = getCardStyles(visualState, delivery.hasProductionRisk ?? false, isHovered);
|
|
10652
|
+
const projectName = delivery.destination || delivery.label;
|
|
9518
10653
|
const handleClick = (e) => {
|
|
9519
10654
|
e.stopPropagation();
|
|
9520
10655
|
onClick?.();
|
|
@@ -9530,38 +10665,24 @@ function DeliveryBadge({
|
|
|
9530
10665
|
e.stopPropagation();
|
|
9531
10666
|
onCommentClick?.();
|
|
9532
10667
|
};
|
|
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
10668
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9546
10669
|
"div",
|
|
9547
10670
|
{
|
|
9548
10671
|
className: cn(
|
|
9549
10672
|
// Position relative for comment button
|
|
9550
10673
|
"relative",
|
|
9551
|
-
// Full-width in cell, 90° corners
|
|
10674
|
+
// Full-width in cell, 90° corners (j3m.radius.none)
|
|
9552
10675
|
"w-full rounded-none",
|
|
9553
|
-
//
|
|
9554
|
-
|
|
9555
|
-
//
|
|
9556
|
-
// - pl-4 = left padding (j3m.spacing.m)
|
|
9557
|
-
// - pr-2 = minimal right padding (progress bar extends further)
|
|
9558
|
-
"min-h-[100px] pt-4 pb-3 pl-4 pr-2",
|
|
9559
|
-
// Card base: dynamic background based on state, complete border
|
|
10676
|
+
// Compact sizing - min-h-[72px], p-4 (j3m.spacing.m)
|
|
10677
|
+
"min-h-[72px] p-4",
|
|
10678
|
+
// Card base: dynamic background based on state
|
|
9560
10679
|
styles.cardBg,
|
|
9561
10680
|
"border border-border",
|
|
9562
10681
|
// Left stroke for status
|
|
9563
10682
|
styles.stroke,
|
|
9564
|
-
//
|
|
10683
|
+
// Opacity for shipped state only
|
|
10684
|
+
styles.opacity,
|
|
10685
|
+
// Interactive states (disabled hover lift for shipped)
|
|
9565
10686
|
"transition-all duration-200 ease-out",
|
|
9566
10687
|
visualState !== "sent" && "hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
9567
10688
|
className
|
|
@@ -9574,7 +10695,7 @@ function DeliveryBadge({
|
|
|
9574
10695
|
variant: "ghost",
|
|
9575
10696
|
size: "icon",
|
|
9576
10697
|
className: cn(
|
|
9577
|
-
"absolute top-
|
|
10698
|
+
"absolute top-1.5 right-1.5",
|
|
9578
10699
|
// 44px touch target for accessibility
|
|
9579
10700
|
"h-11 w-11",
|
|
9580
10701
|
"rounded-full",
|
|
@@ -9606,7 +10727,7 @@ function DeliveryBadge({
|
|
|
9606
10727
|
// Full width, no background (inherits from parent)
|
|
9607
10728
|
"w-full bg-transparent text-left",
|
|
9608
10729
|
// Layout - vertical stack
|
|
9609
|
-
"flex flex-col
|
|
10730
|
+
"flex flex-col justify-between h-full min-h-[40px]",
|
|
9610
10731
|
// Interactive states
|
|
9611
10732
|
"cursor-pointer",
|
|
9612
10733
|
"active:translate-y-0 active:shadow-sm",
|
|
@@ -9614,33 +10735,19 @@ function DeliveryBadge({
|
|
|
9614
10735
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1"
|
|
9615
10736
|
),
|
|
9616
10737
|
children: [
|
|
9617
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
9618
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
), children: delivery.supplierName })
|
|
10738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 pr-12", children: [
|
|
10739
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
10740
|
+
"text-sm font-semibold leading-tight line-clamp-2",
|
|
10741
|
+
styles.titleColor
|
|
10742
|
+
), children: projectName }),
|
|
10743
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 text-red-500 shrink-0 mt-0.5" })
|
|
9624
10744
|
] }),
|
|
9625
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9626
|
-
"
|
|
9627
|
-
|
|
9628
|
-
className:
|
|
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 })
|
|
10745
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 mt-2", children: [
|
|
10746
|
+
visualState === "sent" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10747
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5 text-green-600 dark:text-green-400 shrink-0" }),
|
|
10748
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide", children: "Shipped" })
|
|
9639
10749
|
] }),
|
|
9640
|
-
visualState === "
|
|
9641
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5 text-green-600/60 dark:text-green-400/60 shrink-0" }),
|
|
9642
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground/50 uppercase tracking-wide", children: "Sent" })
|
|
9643
|
-
] })
|
|
10750
|
+
visualState === "ready" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-semibold text-green-600 dark:text-green-400 uppercase tracking-wide", children: "Ready" })
|
|
9644
10751
|
] })
|
|
9645
10752
|
]
|
|
9646
10753
|
}
|
|
@@ -9649,6 +10756,62 @@ function DeliveryBadge({
|
|
|
9649
10756
|
}
|
|
9650
10757
|
);
|
|
9651
10758
|
}
|
|
10759
|
+
function isShippedDelivery(delivery) {
|
|
10760
|
+
return delivery.status === "shipped" || delivery.status === "delivered";
|
|
10761
|
+
}
|
|
10762
|
+
function ShippedDeliveriesToggle({
|
|
10763
|
+
shippedDeliveries,
|
|
10764
|
+
isOpen,
|
|
10765
|
+
onToggle,
|
|
10766
|
+
onDeliveryClick,
|
|
10767
|
+
onDeliveryCommentClick
|
|
10768
|
+
}) {
|
|
10769
|
+
if (shippedDeliveries.length === 0) return null;
|
|
10770
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: isOpen, onOpenChange: onToggle, children: [
|
|
10771
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10772
|
+
"button",
|
|
10773
|
+
{
|
|
10774
|
+
type: "button",
|
|
10775
|
+
className: cn(
|
|
10776
|
+
"w-full flex items-center justify-between gap-2",
|
|
10777
|
+
"min-h-[44px] px-3 py-2",
|
|
10778
|
+
"rounded-md",
|
|
10779
|
+
"text-xs text-muted-foreground",
|
|
10780
|
+
"hover:bg-muted/50 transition-colors",
|
|
10781
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
|
|
10782
|
+
),
|
|
10783
|
+
children: [
|
|
10784
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10785
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5 text-green-600 dark:text-green-400" }),
|
|
10786
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
10787
|
+
"Shipped (",
|
|
10788
|
+
shippedDeliveries.length,
|
|
10789
|
+
")"
|
|
10790
|
+
] })
|
|
10791
|
+
] }),
|
|
10792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10793
|
+
lucideReact.ChevronDown,
|
|
10794
|
+
{
|
|
10795
|
+
className: cn(
|
|
10796
|
+
"h-4 w-4 transition-transform duration-200",
|
|
10797
|
+
isOpen && "rotate-180"
|
|
10798
|
+
)
|
|
10799
|
+
}
|
|
10800
|
+
)
|
|
10801
|
+
]
|
|
10802
|
+
}
|
|
10803
|
+
) }),
|
|
10804
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3 pt-2", children: shippedDeliveries.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10805
|
+
DeliveryBadge,
|
|
10806
|
+
{
|
|
10807
|
+
delivery,
|
|
10808
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
10809
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
10810
|
+
},
|
|
10811
|
+
delivery.id
|
|
10812
|
+
)) }) })
|
|
10813
|
+
] });
|
|
10814
|
+
}
|
|
9652
10815
|
function WeeklyLoadingView({
|
|
9653
10816
|
week,
|
|
9654
10817
|
deliveries,
|
|
@@ -9658,7 +10821,25 @@ function WeeklyLoadingView({
|
|
|
9658
10821
|
showNavigation = true,
|
|
9659
10822
|
className
|
|
9660
10823
|
}) {
|
|
9661
|
-
const
|
|
10824
|
+
const [shippedOpenState, setShippedOpenState] = React29__namespace.useState({
|
|
10825
|
+
1: false,
|
|
10826
|
+
// Monday
|
|
10827
|
+
2: false,
|
|
10828
|
+
// Tuesday
|
|
10829
|
+
3: false,
|
|
10830
|
+
// Wednesday
|
|
10831
|
+
4: false,
|
|
10832
|
+
// Thursday
|
|
10833
|
+
5: false
|
|
10834
|
+
// Friday
|
|
10835
|
+
});
|
|
10836
|
+
const toggleShippedForDay = (dayOfWeek) => {
|
|
10837
|
+
setShippedOpenState((prev) => ({
|
|
10838
|
+
...prev,
|
|
10839
|
+
[dayOfWeek]: !prev[dayOfWeek]
|
|
10840
|
+
}));
|
|
10841
|
+
};
|
|
10842
|
+
const weekDays = React29__namespace.useMemo(() => {
|
|
9662
10843
|
const days = [];
|
|
9663
10844
|
for (let i = 0; i < 5; i++) {
|
|
9664
10845
|
const date = dateFns.addDays(week.startDate, i);
|
|
@@ -9670,22 +10851,26 @@ function WeeklyLoadingView({
|
|
|
9670
10851
|
}
|
|
9671
10852
|
return days;
|
|
9672
10853
|
}, [week.startDate]);
|
|
9673
|
-
const deliveriesByDay =
|
|
10854
|
+
const deliveriesByDay = React29__namespace.useMemo(() => {
|
|
9674
10855
|
const grouped = /* @__PURE__ */ new Map();
|
|
9675
10856
|
for (let i = 1; i <= 5; i++) {
|
|
9676
|
-
grouped.set(i, []);
|
|
10857
|
+
grouped.set(i, { pending: [], shipped: [] });
|
|
9677
10858
|
}
|
|
9678
10859
|
for (const delivery of deliveries) {
|
|
9679
10860
|
const dayOfWeek = delivery.date.getDay();
|
|
9680
10861
|
if (dayOfWeek >= 1 && dayOfWeek <= 5) {
|
|
9681
|
-
const
|
|
9682
|
-
|
|
9683
|
-
|
|
10862
|
+
const dayData = grouped.get(dayOfWeek);
|
|
10863
|
+
if (isShippedDelivery(delivery)) {
|
|
10864
|
+
dayData.shipped.push(delivery);
|
|
10865
|
+
} else {
|
|
10866
|
+
dayData.pending.push(delivery);
|
|
10867
|
+
}
|
|
9684
10868
|
}
|
|
9685
10869
|
}
|
|
9686
10870
|
return grouped;
|
|
9687
10871
|
}, [deliveries]);
|
|
9688
|
-
const
|
|
10872
|
+
const totalPendingDeliveries = deliveries.filter((d) => !isShippedDelivery(d)).length;
|
|
10873
|
+
const totalShippedDeliveries = deliveries.filter((d) => isShippedDelivery(d)).length;
|
|
9689
10874
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col", className), children: [
|
|
9690
10875
|
/* @__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
10876
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
@@ -9702,9 +10887,9 @@ function WeeklyLoadingView({
|
|
|
9702
10887
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
9703
10888
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: week.dateRange }),
|
|
9704
10889
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
9705
|
-
|
|
9706
|
-
" ",
|
|
9707
|
-
|
|
10890
|
+
totalPendingDeliveries,
|
|
10891
|
+
" pending",
|
|
10892
|
+
totalShippedDeliveries > 0 && `, ${totalShippedDeliveries} shipped`
|
|
9708
10893
|
] })
|
|
9709
10894
|
] })
|
|
9710
10895
|
] }),
|
|
@@ -9771,8 +10956,11 @@ function WeeklyLoadingView({
|
|
|
9771
10956
|
dayOfWeek
|
|
9772
10957
|
)) }),
|
|
9773
10958
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-5", children: weekDays.map(({ dayOfWeek, isToday: dayIsToday }) => {
|
|
9774
|
-
const
|
|
9775
|
-
|
|
10959
|
+
const dayData = deliveriesByDay.get(dayOfWeek) ?? { pending: [], shipped: [] };
|
|
10960
|
+
const hasPending = dayData.pending.length > 0;
|
|
10961
|
+
const hasShipped = dayData.shipped.length > 0;
|
|
10962
|
+
const isEmpty = !hasPending && !hasShipped;
|
|
10963
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9776
10964
|
"div",
|
|
9777
10965
|
{
|
|
9778
10966
|
className: cn(
|
|
@@ -9780,22 +10968,39 @@ function WeeklyLoadingView({
|
|
|
9780
10968
|
"flex flex-col p-3",
|
|
9781
10969
|
dayIsToday && "bg-primary/5"
|
|
9782
10970
|
),
|
|
9783
|
-
children:
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
10971
|
+
children: [
|
|
10972
|
+
hasPending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: dayData.pending.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10973
|
+
DeliveryBadge,
|
|
10974
|
+
{
|
|
10975
|
+
delivery,
|
|
10976
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
10977
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
10978
|
+
},
|
|
10979
|
+
delivery.id
|
|
10980
|
+
)) }),
|
|
10981
|
+
hasShipped && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(hasPending && "mt-3"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10982
|
+
ShippedDeliveriesToggle,
|
|
10983
|
+
{
|
|
10984
|
+
shippedDeliveries: dayData.shipped,
|
|
10985
|
+
isOpen: shippedOpenState[dayOfWeek] ?? false,
|
|
10986
|
+
onToggle: () => toggleShippedForDay(dayOfWeek),
|
|
10987
|
+
onDeliveryClick,
|
|
10988
|
+
onDeliveryCommentClick
|
|
10989
|
+
}
|
|
10990
|
+
) }),
|
|
10991
|
+
isEmpty && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-6 text-sm text-muted-foreground/40", children: "\u2014" })
|
|
10992
|
+
]
|
|
9792
10993
|
},
|
|
9793
10994
|
dayOfWeek
|
|
9794
10995
|
);
|
|
9795
10996
|
}) })
|
|
9796
10997
|
] }),
|
|
9797
10998
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden divide-y divide-border", children: weekDays.map(({ date, dayOfWeek, isToday: dayIsToday }) => {
|
|
9798
|
-
const
|
|
10999
|
+
const dayData = deliveriesByDay.get(dayOfWeek) ?? { pending: [], shipped: [] };
|
|
11000
|
+
const hasPending = dayData.pending.length > 0;
|
|
11001
|
+
const hasShipped = dayData.shipped.length > 0;
|
|
11002
|
+
const isEmpty = !hasPending && !hasShipped;
|
|
11003
|
+
dayData.pending.length + dayData.shipped.length;
|
|
9799
11004
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9800
11005
|
"div",
|
|
9801
11006
|
{
|
|
@@ -9818,20 +11023,33 @@ function WeeklyLoadingView({
|
|
|
9818
11023
|
dayIsToday && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-primary font-medium bg-primary/10 px-2 py-0.5 rounded", children: "Today" })
|
|
9819
11024
|
] }),
|
|
9820
11025
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
9821
|
-
|
|
9822
|
-
" ",
|
|
9823
|
-
|
|
11026
|
+
dayData.pending.length,
|
|
11027
|
+
" pending",
|
|
11028
|
+
hasShipped && `, ${dayData.shipped.length} shipped`
|
|
9824
11029
|
] })
|
|
9825
11030
|
] }),
|
|
9826
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
11031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 p-3 pt-0", children: [
|
|
11032
|
+
hasPending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: dayData.pending.map((delivery) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11033
|
+
DeliveryBadge,
|
|
11034
|
+
{
|
|
11035
|
+
delivery,
|
|
11036
|
+
onClick: () => onDeliveryClick?.(delivery),
|
|
11037
|
+
onCommentClick: () => onDeliveryCommentClick?.(delivery)
|
|
11038
|
+
},
|
|
11039
|
+
delivery.id
|
|
11040
|
+
)) }),
|
|
11041
|
+
hasShipped && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11042
|
+
ShippedDeliveriesToggle,
|
|
11043
|
+
{
|
|
11044
|
+
shippedDeliveries: dayData.shipped,
|
|
11045
|
+
isOpen: shippedOpenState[dayOfWeek] ?? false,
|
|
11046
|
+
onToggle: () => toggleShippedForDay(dayOfWeek),
|
|
11047
|
+
onDeliveryClick,
|
|
11048
|
+
onDeliveryCommentClick
|
|
11049
|
+
}
|
|
11050
|
+
),
|
|
11051
|
+
isEmpty && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground/40 py-4 text-center", children: "\u2014" })
|
|
11052
|
+
] })
|
|
9835
11053
|
]
|
|
9836
11054
|
},
|
|
9837
11055
|
dayOfWeek
|
|
@@ -9840,36 +11058,63 @@ function WeeklyLoadingView({
|
|
|
9840
11058
|
] })
|
|
9841
11059
|
] });
|
|
9842
11060
|
}
|
|
9843
|
-
function
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
11061
|
+
function getTimelineState(delivery) {
|
|
11062
|
+
const isShipped = delivery.status === "shipped" || delivery.status === "delivered";
|
|
11063
|
+
const isReady = delivery.isReadyToUnload ?? false;
|
|
11064
|
+
const hasProductionData = delivery.producedCount !== void 0 || delivery.producedTons !== void 0;
|
|
11065
|
+
if (isShipped) {
|
|
11066
|
+
return {
|
|
11067
|
+
currentStep: "delivery",
|
|
11068
|
+
documentState: "completed",
|
|
11069
|
+
productionState: "completed",
|
|
11070
|
+
deliveryState: "completed",
|
|
11071
|
+
isReady: true,
|
|
11072
|
+
currentStepLabel: "Delivery",
|
|
11073
|
+
reason: "Delivery completed"
|
|
11074
|
+
};
|
|
9856
11075
|
}
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
11076
|
+
if (isReady) {
|
|
11077
|
+
return {
|
|
11078
|
+
currentStep: "delivery",
|
|
11079
|
+
documentState: "completed",
|
|
11080
|
+
productionState: "completed",
|
|
11081
|
+
deliveryState: "current",
|
|
11082
|
+
isReady: true,
|
|
11083
|
+
currentStepLabel: "Delivery",
|
|
11084
|
+
reason: "All prerequisites complete"
|
|
11085
|
+
};
|
|
11086
|
+
}
|
|
11087
|
+
if (hasProductionData) {
|
|
11088
|
+
return {
|
|
11089
|
+
currentStep: "production",
|
|
11090
|
+
documentState: "completed",
|
|
11091
|
+
productionState: "current",
|
|
11092
|
+
deliveryState: "upcoming",
|
|
11093
|
+
isReady: false,
|
|
11094
|
+
currentStepLabel: "Production",
|
|
11095
|
+
reason: delivery.hasProductionRisk ? delivery.riskReason || "Production delay risk" : "Not all items have been produced"
|
|
11096
|
+
};
|
|
11097
|
+
}
|
|
11098
|
+
if (delivery.status === "planned") {
|
|
11099
|
+
return {
|
|
11100
|
+
currentStep: "document",
|
|
11101
|
+
documentState: "current",
|
|
11102
|
+
productionState: "upcoming",
|
|
11103
|
+
deliveryState: "upcoming",
|
|
11104
|
+
isReady: false,
|
|
11105
|
+
currentStepLabel: "Document",
|
|
11106
|
+
reason: "Waiting for document approval"
|
|
11107
|
+
};
|
|
9872
11108
|
}
|
|
11109
|
+
return {
|
|
11110
|
+
currentStep: "production",
|
|
11111
|
+
documentState: "completed",
|
|
11112
|
+
productionState: "current",
|
|
11113
|
+
deliveryState: "upcoming",
|
|
11114
|
+
isReady: false,
|
|
11115
|
+
currentStepLabel: "Production",
|
|
11116
|
+
reason: "Production status pending"
|
|
11117
|
+
};
|
|
9873
11118
|
}
|
|
9874
11119
|
function getElementStatusBadgeClasses(status) {
|
|
9875
11120
|
switch (status) {
|
|
@@ -9885,6 +11130,166 @@ function getElementStatusBadgeClasses(status) {
|
|
|
9885
11130
|
return "border-muted-foreground/50 text-muted-foreground";
|
|
9886
11131
|
}
|
|
9887
11132
|
}
|
|
11133
|
+
var TIMELINE_STEPS = [
|
|
11134
|
+
{ id: "document", label: "Document", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "h-4 w-4" }) },
|
|
11135
|
+
{ id: "production", label: "Production", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-4 w-4" }) },
|
|
11136
|
+
{ id: "delivery", label: "Delivery", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4" }) }
|
|
11137
|
+
];
|
|
11138
|
+
function getStepStyles(state) {
|
|
11139
|
+
switch (state) {
|
|
11140
|
+
case "completed":
|
|
11141
|
+
return {
|
|
11142
|
+
dot: "bg-green-500/20 border-green-500",
|
|
11143
|
+
icon: "text-green-600 dark:text-green-400",
|
|
11144
|
+
label: "text-muted-foreground",
|
|
11145
|
+
line: "bg-green-500"
|
|
11146
|
+
};
|
|
11147
|
+
case "current":
|
|
11148
|
+
return {
|
|
11149
|
+
dot: "bg-primary/20 border-primary",
|
|
11150
|
+
icon: "text-primary",
|
|
11151
|
+
label: "text-foreground font-semibold",
|
|
11152
|
+
line: "bg-border"
|
|
11153
|
+
};
|
|
11154
|
+
case "upcoming":
|
|
11155
|
+
default:
|
|
11156
|
+
return {
|
|
11157
|
+
dot: "bg-muted border-border",
|
|
11158
|
+
icon: "text-muted-foreground/50",
|
|
11159
|
+
label: "text-muted-foreground/50",
|
|
11160
|
+
line: "bg-border"
|
|
11161
|
+
};
|
|
11162
|
+
}
|
|
11163
|
+
}
|
|
11164
|
+
function DeliveryTimeline({ timelineState }) {
|
|
11165
|
+
const getStateForStep = (stepId) => {
|
|
11166
|
+
switch (stepId) {
|
|
11167
|
+
case "document":
|
|
11168
|
+
return timelineState.documentState;
|
|
11169
|
+
case "production":
|
|
11170
|
+
return timelineState.productionState;
|
|
11171
|
+
case "delivery":
|
|
11172
|
+
return timelineState.deliveryState;
|
|
11173
|
+
}
|
|
11174
|
+
};
|
|
11175
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between w-full", children: TIMELINE_STEPS.map((step, index) => {
|
|
11176
|
+
const state = getStateForStep(step.id);
|
|
11177
|
+
const styles = getStepStyles(state);
|
|
11178
|
+
const isLast = index === TIMELINE_STEPS.length - 1;
|
|
11179
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React29__namespace.Fragment, { children: [
|
|
11180
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
11181
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11182
|
+
"div",
|
|
11183
|
+
{
|
|
11184
|
+
className: cn(
|
|
11185
|
+
"flex items-center justify-center",
|
|
11186
|
+
"h-10 w-10 rounded-full border-2",
|
|
11187
|
+
"transition-colors duration-200",
|
|
11188
|
+
styles.dot
|
|
11189
|
+
),
|
|
11190
|
+
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 })
|
|
11191
|
+
}
|
|
11192
|
+
),
|
|
11193
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs", styles.label), children: step.label })
|
|
11194
|
+
] }),
|
|
11195
|
+
!isLast && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 mx-2 mb-6", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11196
|
+
"div",
|
|
11197
|
+
{
|
|
11198
|
+
className: cn(
|
|
11199
|
+
"h-0.5 w-full rounded-full",
|
|
11200
|
+
styles.line
|
|
11201
|
+
)
|
|
11202
|
+
}
|
|
11203
|
+
) })
|
|
11204
|
+
] }, step.id);
|
|
11205
|
+
}) });
|
|
11206
|
+
}
|
|
11207
|
+
function PackingStatusBadge({
|
|
11208
|
+
timelineState,
|
|
11209
|
+
hasRisk
|
|
11210
|
+
}) {
|
|
11211
|
+
const getPackingStatus = () => {
|
|
11212
|
+
if (timelineState.isReady) {
|
|
11213
|
+
return {
|
|
11214
|
+
label: "Ready",
|
|
11215
|
+
className: "bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300 border-green-200 dark:border-green-800"
|
|
11216
|
+
};
|
|
11217
|
+
}
|
|
11218
|
+
if (hasRisk) {
|
|
11219
|
+
return {
|
|
11220
|
+
label: "At risk",
|
|
11221
|
+
className: "bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300 border-red-200 dark:border-red-800"
|
|
11222
|
+
};
|
|
11223
|
+
}
|
|
11224
|
+
switch (timelineState.currentStep) {
|
|
11225
|
+
case "document":
|
|
11226
|
+
return {
|
|
11227
|
+
label: "Pending approval",
|
|
11228
|
+
className: "bg-muted text-muted-foreground border-border"
|
|
11229
|
+
};
|
|
11230
|
+
case "production":
|
|
11231
|
+
return {
|
|
11232
|
+
label: "In production",
|
|
11233
|
+
className: "bg-amber-100 dark:bg-amber-900/50 text-amber-700 dark:text-amber-300 border-amber-200 dark:border-amber-800"
|
|
11234
|
+
};
|
|
11235
|
+
default:
|
|
11236
|
+
return {
|
|
11237
|
+
label: "Not ready",
|
|
11238
|
+
className: "bg-muted text-muted-foreground border-border"
|
|
11239
|
+
};
|
|
11240
|
+
}
|
|
11241
|
+
};
|
|
11242
|
+
const status = getPackingStatus();
|
|
11243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11244
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Packing status:" }),
|
|
11245
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
11246
|
+
"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border",
|
|
11247
|
+
status.className
|
|
11248
|
+
), children: status.label })
|
|
11249
|
+
] });
|
|
11250
|
+
}
|
|
11251
|
+
function ReadinessMessage({
|
|
11252
|
+
timelineState,
|
|
11253
|
+
hasRisk
|
|
11254
|
+
}) {
|
|
11255
|
+
if (timelineState.isReady && timelineState.deliveryState === "completed") {
|
|
11256
|
+
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: [
|
|
11257
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11258
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 text-green-600 dark:text-green-400 shrink-0" }),
|
|
11259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-green-700 dark:text-green-300", children: "Shipped" })
|
|
11260
|
+
] }),
|
|
11261
|
+
/* @__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." })
|
|
11262
|
+
] });
|
|
11263
|
+
}
|
|
11264
|
+
if (timelineState.isReady) {
|
|
11265
|
+
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: [
|
|
11266
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11267
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 text-green-600 dark:text-green-400 shrink-0" }),
|
|
11268
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-green-700 dark:text-green-300", children: "Ready" })
|
|
11269
|
+
] }),
|
|
11270
|
+
/* @__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." })
|
|
11271
|
+
] });
|
|
11272
|
+
}
|
|
11273
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11274
|
+
"rounded-lg p-3 border",
|
|
11275
|
+
hasRisk ? "bg-red-50/50 dark:bg-red-950/20 border-red-200 dark:border-red-800/50" : "bg-muted/50 border-border"
|
|
11276
|
+
), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
11277
|
+
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" }),
|
|
11278
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
11279
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
11280
|
+
"text-sm font-medium",
|
|
11281
|
+
hasRisk ? "text-red-700 dark:text-red-300" : "text-foreground"
|
|
11282
|
+
), children: [
|
|
11283
|
+
"Currently in: ",
|
|
11284
|
+
timelineState.currentStepLabel
|
|
11285
|
+
] }),
|
|
11286
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(
|
|
11287
|
+
"text-xs mt-0.5",
|
|
11288
|
+
hasRisk ? "text-red-600/80 dark:text-red-400/80" : "text-muted-foreground"
|
|
11289
|
+
), children: timelineState.reason })
|
|
11290
|
+
] })
|
|
11291
|
+
] }) });
|
|
11292
|
+
}
|
|
9888
11293
|
function getElementRowBg(status) {
|
|
9889
11294
|
switch (status) {
|
|
9890
11295
|
case "loaded":
|
|
@@ -9906,7 +11311,7 @@ function AddCommentDialog({
|
|
|
9906
11311
|
weekId,
|
|
9907
11312
|
onAddComment
|
|
9908
11313
|
}) {
|
|
9909
|
-
const [commentText, setCommentText] =
|
|
11314
|
+
const [commentText, setCommentText] = React29__namespace.useState("");
|
|
9910
11315
|
const handleSubmit = () => {
|
|
9911
11316
|
if (commentText.trim() && onAddComment) {
|
|
9912
11317
|
onAddComment({
|
|
@@ -9931,7 +11336,7 @@ function AddCommentDialog({
|
|
|
9931
11336
|
handleSubmit();
|
|
9932
11337
|
}
|
|
9933
11338
|
};
|
|
9934
|
-
|
|
11339
|
+
React29__namespace.useEffect(() => {
|
|
9935
11340
|
if (!open) {
|
|
9936
11341
|
setCommentText("");
|
|
9937
11342
|
}
|
|
@@ -9994,8 +11399,8 @@ function CommentsSection({
|
|
|
9994
11399
|
weekId,
|
|
9995
11400
|
onAddComment
|
|
9996
11401
|
}) {
|
|
9997
|
-
const [viewCommentsOpen, setViewCommentsOpen] =
|
|
9998
|
-
const [addDialogOpen, setAddDialogOpen] =
|
|
11402
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React29__namespace.useState(true);
|
|
11403
|
+
const [addDialogOpen, setAddDialogOpen] = React29__namespace.useState(false);
|
|
9999
11404
|
const formatDate3 = (date) => {
|
|
10000
11405
|
return new Intl.DateTimeFormat("en-US", {
|
|
10001
11406
|
month: "short",
|
|
@@ -10058,31 +11463,6 @@ function CommentsSection({
|
|
|
10058
11463
|
)
|
|
10059
11464
|
] });
|
|
10060
11465
|
}
|
|
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
11466
|
function DeliveryDetailPage({
|
|
10087
11467
|
delivery,
|
|
10088
11468
|
week,
|
|
@@ -10093,14 +11473,8 @@ function DeliveryDetailPage({
|
|
|
10093
11473
|
onAddComment,
|
|
10094
11474
|
onConfirmLoad
|
|
10095
11475
|
}) {
|
|
10096
|
-
const
|
|
10097
|
-
const
|
|
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;
|
|
10103
|
-
const elementsByStatus = React27__namespace.useMemo(() => {
|
|
11476
|
+
const timelineState = getTimelineState(delivery);
|
|
11477
|
+
const elementsByStatus = React29__namespace.useMemo(() => {
|
|
10104
11478
|
const loaded = delivery.elements.filter((e) => e.status === "loaded");
|
|
10105
11479
|
const missing = delivery.elements.filter((e) => e.status === "missing");
|
|
10106
11480
|
const moved = delivery.elements.filter((e) => e.status === "moved");
|
|
@@ -10108,6 +11482,7 @@ function DeliveryDetailPage({
|
|
|
10108
11482
|
return { loaded, missing, moved, addons };
|
|
10109
11483
|
}, [delivery.elements]);
|
|
10110
11484
|
const preLoadingComments = delivery.comments.filter((c) => c.context === "pre_unloading");
|
|
11485
|
+
const projectName = delivery.destination || delivery.label;
|
|
10111
11486
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
10112
11487
|
/* @__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
11488
|
Button,
|
|
@@ -10123,129 +11498,39 @@ function DeliveryDetailPage({
|
|
|
10123
11498
|
}
|
|
10124
11499
|
) }),
|
|
10125
11500
|
/* @__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-
|
|
11501
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pt-4 space-y-3", children: [
|
|
10127
11502
|
/* @__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
|
-
] })
|
|
11503
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold leading-tight line-clamp-2", children: projectName }),
|
|
11504
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-5 w-5 text-red-500 shrink-0 mt-0.5" })
|
|
10163
11505
|
] }),
|
|
10164
|
-
|
|
10165
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
10166
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
10167
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
11506
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground", children: [
|
|
11507
|
+
delivery.location && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
11508
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
11509
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: delivery.location })
|
|
10168
11510
|
] }),
|
|
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
11511
|
/* @__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
|
-
] })
|
|
11512
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
11513
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
11514
|
+
"Expected on site: ",
|
|
11515
|
+
delivery.date.toLocaleDateString("en-US", {
|
|
11516
|
+
day: "numeric",
|
|
11517
|
+
month: "short",
|
|
11518
|
+
year: "numeric"
|
|
11519
|
+
})
|
|
10246
11520
|
] })
|
|
10247
11521
|
] })
|
|
10248
|
-
] })
|
|
11522
|
+
] }),
|
|
11523
|
+
/* @__PURE__ */ jsxRuntime.jsx(PackingStatusBadge, { timelineState, hasRisk: delivery.hasProductionRisk ?? false })
|
|
11524
|
+
] }),
|
|
11525
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
11526
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: /* @__PURE__ */ jsxRuntime.jsx(DeliveryTimeline, { timelineState }) }),
|
|
11527
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11528
|
+
ReadinessMessage,
|
|
11529
|
+
{
|
|
11530
|
+
timelineState,
|
|
11531
|
+
hasRisk: delivery.hasProductionRisk ?? false
|
|
11532
|
+
}
|
|
11533
|
+
)
|
|
10249
11534
|
] }),
|
|
10250
11535
|
(elementsByStatus.loaded.length > 0 || elementsByStatus.missing.length > 0 || elementsByStatus.moved.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
|
|
10251
11536
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -10376,11 +11661,11 @@ function SupplierWeeklyLoading({
|
|
|
10376
11661
|
bordered = true,
|
|
10377
11662
|
className
|
|
10378
11663
|
}) {
|
|
10379
|
-
const [selectedDelivery, setSelectedDelivery] =
|
|
10380
|
-
const [sheetOpen, setSheetOpen] =
|
|
10381
|
-
const [commentDelivery, setCommentDelivery] =
|
|
10382
|
-
const [commentDialogOpen, setCommentDialogOpen] =
|
|
10383
|
-
const [commentText, setCommentText] =
|
|
11664
|
+
const [selectedDelivery, setSelectedDelivery] = React29__namespace.useState(null);
|
|
11665
|
+
const [sheetOpen, setSheetOpen] = React29__namespace.useState(false);
|
|
11666
|
+
const [commentDelivery, setCommentDelivery] = React29__namespace.useState(null);
|
|
11667
|
+
const [commentDialogOpen, setCommentDialogOpen] = React29__namespace.useState(false);
|
|
11668
|
+
const [commentText, setCommentText] = React29__namespace.useState("");
|
|
10384
11669
|
const handleDeliveryClick = (delivery) => {
|
|
10385
11670
|
setSelectedDelivery(delivery);
|
|
10386
11671
|
setSheetOpen(true);
|
|
@@ -10524,59 +11809,36 @@ function SupplierWeeklyLoading({
|
|
|
10524
11809
|
] }) })
|
|
10525
11810
|
] });
|
|
10526
11811
|
}
|
|
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) {
|
|
11812
|
+
function getCardStyles2(state, hasRisk, isHovered) {
|
|
10559
11813
|
if (hasRisk) {
|
|
10560
11814
|
return {
|
|
10561
|
-
stroke: "border-l-
|
|
10562
|
-
|
|
11815
|
+
stroke: "border-l-[3px] border-l-red-500",
|
|
11816
|
+
cardBg: "bg-background",
|
|
11817
|
+
titleColor: "text-foreground",
|
|
11818
|
+
opacity: ""
|
|
10563
11819
|
};
|
|
10564
11820
|
}
|
|
10565
11821
|
switch (state) {
|
|
10566
11822
|
case "sent":
|
|
10567
11823
|
return {
|
|
10568
|
-
stroke: "border-l-
|
|
10569
|
-
|
|
11824
|
+
stroke: "border-l-[3px] border-l-green-500/40",
|
|
11825
|
+
cardBg: "bg-muted/40",
|
|
11826
|
+
titleColor: "text-muted-foreground",
|
|
11827
|
+
opacity: "opacity-60"
|
|
10570
11828
|
};
|
|
10571
11829
|
case "ready":
|
|
10572
11830
|
return {
|
|
10573
|
-
stroke: "border-l-
|
|
10574
|
-
|
|
11831
|
+
stroke: "border-l-[4px] border-l-green-500",
|
|
11832
|
+
cardBg: "bg-background",
|
|
11833
|
+
titleColor: "text-foreground",
|
|
11834
|
+
opacity: ""
|
|
10575
11835
|
};
|
|
10576
11836
|
default:
|
|
10577
11837
|
return {
|
|
10578
|
-
stroke: isHovered ? "border-l-
|
|
10579
|
-
|
|
11838
|
+
stroke: isHovered ? "border-l-[3px] border-l-primary/50" : "border-l-[3px] border-l-border",
|
|
11839
|
+
cardBg: "bg-background",
|
|
11840
|
+
titleColor: "text-foreground",
|
|
11841
|
+
opacity: ""
|
|
10580
11842
|
};
|
|
10581
11843
|
}
|
|
10582
11844
|
}
|
|
@@ -10585,22 +11847,11 @@ function DeliveryCard({
|
|
|
10585
11847
|
onTap,
|
|
10586
11848
|
className
|
|
10587
11849
|
}) {
|
|
10588
|
-
const [isHovered, setIsHovered] =
|
|
11850
|
+
const [isHovered, setIsHovered] = React29__namespace.useState(false);
|
|
10589
11851
|
const hasComments = delivery.comments.length > 0;
|
|
10590
11852
|
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]);
|
|
11853
|
+
const styles = getCardStyles2(visualState, delivery.hasProductionRisk ?? false, isHovered);
|
|
11854
|
+
const projectName = delivery.destination || delivery.label;
|
|
10604
11855
|
const handleClick = () => {
|
|
10605
11856
|
onTap?.();
|
|
10606
11857
|
};
|
|
@@ -10624,69 +11875,43 @@ function DeliveryCard({
|
|
|
10624
11875
|
"w-full rounded-none",
|
|
10625
11876
|
// Touch-friendly sizing - 56px min-height for iPad
|
|
10626
11877
|
"min-h-[56px] p-4",
|
|
10627
|
-
// Card styling:
|
|
10628
|
-
|
|
10629
|
-
|
|
11878
|
+
// Card styling: dynamic background based on state
|
|
11879
|
+
styles.cardBg,
|
|
11880
|
+
"border border-border",
|
|
11881
|
+
// Left stroke for status
|
|
10630
11882
|
styles.stroke,
|
|
10631
|
-
//
|
|
11883
|
+
// Opacity for shipped state only
|
|
11884
|
+
styles.opacity,
|
|
11885
|
+
// Hover/tap state - lift effect (disabled for shipped)
|
|
10632
11886
|
"cursor-pointer transition-all duration-200 ease-out",
|
|
10633
|
-
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
11887
|
+
visualState !== "sent" && "hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
10634
11888
|
"active:translate-y-0 active:shadow-sm",
|
|
10635
11889
|
// Focus state
|
|
10636
11890
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
10637
|
-
// Greyed out for sent state
|
|
10638
|
-
visualState === "sent" && "opacity-60",
|
|
10639
11891
|
className
|
|
10640
11892
|
),
|
|
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
|
-
] })
|
|
11893
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
11894
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0 flex-1", children: [
|
|
11895
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11896
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
11897
|
+
"text-sm font-semibold truncate",
|
|
11898
|
+
styles.titleColor
|
|
11899
|
+
), children: projectName }),
|
|
11900
|
+
delivery.hasProductionRisk && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 text-red-500 shrink-0" }),
|
|
11901
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
|
|
11902
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
11903
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-primary" })
|
|
10676
11904
|
] })
|
|
11905
|
+
] }),
|
|
11906
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
11907
|
+
visualState === "sent" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11908
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5 text-green-600 dark:text-green-400 shrink-0" }),
|
|
11909
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide", children: "Shipped" })
|
|
11910
|
+
] }),
|
|
11911
|
+
visualState === "ready" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-semibold text-green-600 dark:text-green-400 uppercase tracking-wide", children: "Ready" })
|
|
10677
11912
|
] })
|
|
10678
11913
|
] }),
|
|
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
|
-
] })
|
|
11914
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 text-muted-foreground shrink-0" })
|
|
10690
11915
|
] })
|
|
10691
11916
|
}
|
|
10692
11917
|
);
|
|
@@ -10754,7 +11979,7 @@ var BADGE_VARIANT_LABELS = {
|
|
|
10754
11979
|
colored: "Colored",
|
|
10755
11980
|
mixed: "Mixed"
|
|
10756
11981
|
};
|
|
10757
|
-
var CalendarContext =
|
|
11982
|
+
var CalendarContext = React29__namespace.createContext(null);
|
|
10758
11983
|
function EventCalendarProvider({
|
|
10759
11984
|
children,
|
|
10760
11985
|
events: initialEvents = [],
|
|
@@ -10769,38 +11994,38 @@ function EventCalendarProvider({
|
|
|
10769
11994
|
onEventUpdate,
|
|
10770
11995
|
onEventDelete
|
|
10771
11996
|
}) {
|
|
10772
|
-
const [selectedDate, setSelectedDate] =
|
|
10773
|
-
const [selectedUserId, setSelectedUserId] =
|
|
10774
|
-
const [events, setEventsState] =
|
|
10775
|
-
const [users] =
|
|
10776
|
-
const [badgeVariant, setBadgeVariant] =
|
|
10777
|
-
const [view, setView] =
|
|
10778
|
-
const [workingHours, setWorkingHours] =
|
|
10779
|
-
const [visibleHours, setVisibleHours] =
|
|
10780
|
-
|
|
11997
|
+
const [selectedDate, setSelectedDate] = React29__namespace.useState(defaultDate);
|
|
11998
|
+
const [selectedUserId, setSelectedUserId] = React29__namespace.useState(defaultUserId);
|
|
11999
|
+
const [events, setEventsState] = React29__namespace.useState(initialEvents);
|
|
12000
|
+
const [users] = React29__namespace.useState(initialUsers);
|
|
12001
|
+
const [badgeVariant, setBadgeVariant] = React29__namespace.useState(defaultBadgeVariant);
|
|
12002
|
+
const [view, setView] = React29__namespace.useState(defaultView);
|
|
12003
|
+
const [workingHours, setWorkingHours] = React29__namespace.useState(defaultWorkingHours);
|
|
12004
|
+
const [visibleHours, setVisibleHours] = React29__namespace.useState(defaultVisibleHours);
|
|
12005
|
+
React29__namespace.useEffect(() => {
|
|
10781
12006
|
setEventsState(initialEvents);
|
|
10782
12007
|
}, [initialEvents]);
|
|
10783
|
-
const setEvents =
|
|
12008
|
+
const setEvents = React29__namespace.useCallback((newEvents) => {
|
|
10784
12009
|
setEventsState(newEvents);
|
|
10785
12010
|
}, []);
|
|
10786
|
-
const addEvent =
|
|
12011
|
+
const addEvent = React29__namespace.useCallback((event) => {
|
|
10787
12012
|
setEventsState((prev) => [...prev, event]);
|
|
10788
12013
|
onEventAdd?.(event);
|
|
10789
12014
|
}, [onEventAdd]);
|
|
10790
|
-
const updateEvent =
|
|
12015
|
+
const updateEvent = React29__namespace.useCallback((event) => {
|
|
10791
12016
|
setEventsState(
|
|
10792
12017
|
(prev) => prev.map((e) => e.id === event.id ? event : e)
|
|
10793
12018
|
);
|
|
10794
12019
|
onEventUpdate?.(event);
|
|
10795
12020
|
}, [onEventUpdate]);
|
|
10796
|
-
const deleteEvent =
|
|
12021
|
+
const deleteEvent = React29__namespace.useCallback((eventId) => {
|
|
10797
12022
|
setEventsState((prev) => prev.filter((e) => e.id !== eventId));
|
|
10798
12023
|
onEventDelete?.(eventId);
|
|
10799
12024
|
}, [onEventDelete]);
|
|
10800
|
-
const goToToday =
|
|
12025
|
+
const goToToday = React29__namespace.useCallback(() => {
|
|
10801
12026
|
setSelectedDate(/* @__PURE__ */ new Date());
|
|
10802
12027
|
}, []);
|
|
10803
|
-
const goToPrevious =
|
|
12028
|
+
const goToPrevious = React29__namespace.useCallback(() => {
|
|
10804
12029
|
setSelectedDate((current) => {
|
|
10805
12030
|
switch (view) {
|
|
10806
12031
|
case "day":
|
|
@@ -10818,7 +12043,7 @@ function EventCalendarProvider({
|
|
|
10818
12043
|
}
|
|
10819
12044
|
});
|
|
10820
12045
|
}, [view]);
|
|
10821
|
-
const goToNext =
|
|
12046
|
+
const goToNext = React29__namespace.useCallback(() => {
|
|
10822
12047
|
setSelectedDate((current) => {
|
|
10823
12048
|
switch (view) {
|
|
10824
12049
|
case "day":
|
|
@@ -10836,7 +12061,7 @@ function EventCalendarProvider({
|
|
|
10836
12061
|
}
|
|
10837
12062
|
});
|
|
10838
12063
|
}, [view]);
|
|
10839
|
-
const contextValue =
|
|
12064
|
+
const contextValue = React29__namespace.useMemo(
|
|
10840
12065
|
() => ({
|
|
10841
12066
|
// State
|
|
10842
12067
|
selectedDate,
|
|
@@ -10883,7 +12108,7 @@ function EventCalendarProvider({
|
|
|
10883
12108
|
return /* @__PURE__ */ jsxRuntime.jsx(CalendarContext.Provider, { value: contextValue, children });
|
|
10884
12109
|
}
|
|
10885
12110
|
function useEventCalendar() {
|
|
10886
|
-
const context =
|
|
12111
|
+
const context = React29__namespace.useContext(CalendarContext);
|
|
10887
12112
|
if (!context) {
|
|
10888
12113
|
throw new Error("useEventCalendar must be used within an EventCalendarProvider");
|
|
10889
12114
|
}
|
|
@@ -10891,14 +12116,14 @@ function useEventCalendar() {
|
|
|
10891
12116
|
}
|
|
10892
12117
|
function useFilteredEvents() {
|
|
10893
12118
|
const { events, selectedUserId } = useEventCalendar();
|
|
10894
|
-
return
|
|
12119
|
+
return React29__namespace.useMemo(() => {
|
|
10895
12120
|
if (!selectedUserId) return events;
|
|
10896
12121
|
return events.filter((event) => event.user.id === selectedUserId);
|
|
10897
12122
|
}, [events, selectedUserId]);
|
|
10898
12123
|
}
|
|
10899
12124
|
function useEventsInRange(startDate, endDate) {
|
|
10900
12125
|
const filteredEvents = useFilteredEvents();
|
|
10901
|
-
return
|
|
12126
|
+
return React29__namespace.useMemo(() => {
|
|
10902
12127
|
return filteredEvents.filter((event) => {
|
|
10903
12128
|
const eventStart = new Date(event.startDate);
|
|
10904
12129
|
const eventEnd = new Date(event.endDate);
|
|
@@ -11456,8 +12681,8 @@ function MoreEvents({ count, onClick, className }) {
|
|
|
11456
12681
|
);
|
|
11457
12682
|
}
|
|
11458
12683
|
function TimeIndicator({ className }) {
|
|
11459
|
-
const [now, setNow] =
|
|
11460
|
-
|
|
12684
|
+
const [now, setNow] = React29__namespace.useState(/* @__PURE__ */ new Date());
|
|
12685
|
+
React29__namespace.useEffect(() => {
|
|
11461
12686
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
11462
12687
|
return () => clearInterval(interval);
|
|
11463
12688
|
}, []);
|
|
@@ -11494,24 +12719,24 @@ function DateBadge({ date, className }) {
|
|
|
11494
12719
|
}
|
|
11495
12720
|
);
|
|
11496
12721
|
}
|
|
11497
|
-
var DragContext =
|
|
12722
|
+
var DragContext = React29__namespace.createContext(null);
|
|
11498
12723
|
function DragProvider({
|
|
11499
12724
|
children,
|
|
11500
12725
|
snapMinutes = 15,
|
|
11501
12726
|
onDragStart,
|
|
11502
12727
|
onDragEnd
|
|
11503
12728
|
}) {
|
|
11504
|
-
const [draggedEvent, setDraggedEventState] =
|
|
11505
|
-
const [isDragging, setIsDragging] =
|
|
12729
|
+
const [draggedEvent, setDraggedEventState] = React29__namespace.useState(null);
|
|
12730
|
+
const [isDragging, setIsDragging] = React29__namespace.useState(false);
|
|
11506
12731
|
const { updateEvent } = useEventCalendar();
|
|
11507
|
-
const setDraggedEvent =
|
|
12732
|
+
const setDraggedEvent = React29__namespace.useCallback((event) => {
|
|
11508
12733
|
setDraggedEventState(event);
|
|
11509
12734
|
setIsDragging(!!event);
|
|
11510
12735
|
if (event) {
|
|
11511
12736
|
onDragStart?.(event);
|
|
11512
12737
|
}
|
|
11513
12738
|
}, [onDragStart]);
|
|
11514
|
-
const handleDrop =
|
|
12739
|
+
const handleDrop = React29__namespace.useCallback((newStartDate) => {
|
|
11515
12740
|
if (!draggedEvent) return;
|
|
11516
12741
|
const snappedDate = snapToInterval(newStartDate, snapMinutes);
|
|
11517
12742
|
const { startDate, endDate } = calculateDropDates(draggedEvent, snappedDate);
|
|
@@ -11524,7 +12749,7 @@ function DragProvider({
|
|
|
11524
12749
|
onDragEnd?.(updatedEvent, new Date(startDate), new Date(endDate));
|
|
11525
12750
|
setDraggedEvent(null);
|
|
11526
12751
|
}, [draggedEvent, snapMinutes, updateEvent, onDragEnd, setDraggedEvent]);
|
|
11527
|
-
const contextValue =
|
|
12752
|
+
const contextValue = React29__namespace.useMemo(
|
|
11528
12753
|
() => ({
|
|
11529
12754
|
draggedEvent,
|
|
11530
12755
|
setDraggedEvent,
|
|
@@ -11535,7 +12760,7 @@ function DragProvider({
|
|
|
11535
12760
|
return /* @__PURE__ */ jsxRuntime.jsx(DragContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(DragDropHandler, { onDrop: handleDrop, children }) });
|
|
11536
12761
|
}
|
|
11537
12762
|
function useDrag() {
|
|
11538
|
-
const context =
|
|
12763
|
+
const context = React29__namespace.useContext(DragContext);
|
|
11539
12764
|
if (!context) {
|
|
11540
12765
|
throw new Error("useDrag must be used within a DragProvider");
|
|
11541
12766
|
}
|
|
@@ -11580,7 +12805,7 @@ function DroppableZone({
|
|
|
11580
12805
|
}) {
|
|
11581
12806
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
11582
12807
|
const { updateEvent } = useEventCalendar();
|
|
11583
|
-
const [isOver, setIsOver] =
|
|
12808
|
+
const [isOver, setIsOver] = React29__namespace.useState(false);
|
|
11584
12809
|
const handleDragOver = (e) => {
|
|
11585
12810
|
e.preventDefault();
|
|
11586
12811
|
e.dataTransfer.dropEffect = "move";
|
|
@@ -11618,23 +12843,23 @@ function DroppableZone({
|
|
|
11618
12843
|
function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
11619
12844
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
11620
12845
|
const { updateEvent } = useEventCalendar();
|
|
11621
|
-
const [isOver, setIsOver] =
|
|
11622
|
-
const dropTargetDate =
|
|
12846
|
+
const [isOver, setIsOver] = React29__namespace.useState(false);
|
|
12847
|
+
const dropTargetDate = React29__namespace.useMemo(() => {
|
|
11623
12848
|
const targetDate = new Date(date);
|
|
11624
12849
|
if (hour !== void 0) {
|
|
11625
12850
|
targetDate.setHours(hour, minute, 0, 0);
|
|
11626
12851
|
}
|
|
11627
12852
|
return targetDate;
|
|
11628
12853
|
}, [date, hour, minute]);
|
|
11629
|
-
const handleDragOver =
|
|
12854
|
+
const handleDragOver = React29__namespace.useCallback((e) => {
|
|
11630
12855
|
e.preventDefault();
|
|
11631
12856
|
e.dataTransfer.dropEffect = "move";
|
|
11632
12857
|
if (!isOver) setIsOver(true);
|
|
11633
12858
|
}, [isOver]);
|
|
11634
|
-
const handleDragLeave =
|
|
12859
|
+
const handleDragLeave = React29__namespace.useCallback(() => {
|
|
11635
12860
|
setIsOver(false);
|
|
11636
12861
|
}, []);
|
|
11637
|
-
const handleDrop =
|
|
12862
|
+
const handleDrop = React29__namespace.useCallback((e) => {
|
|
11638
12863
|
e.preventDefault();
|
|
11639
12864
|
setIsOver(false);
|
|
11640
12865
|
if (!draggedEvent) return;
|
|
@@ -11661,13 +12886,13 @@ function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
|
11661
12886
|
function useDraggable(event, disabled = false) {
|
|
11662
12887
|
const { setDraggedEvent, draggedEvent } = useDrag();
|
|
11663
12888
|
const isDragged = draggedEvent?.id === event.id;
|
|
11664
|
-
const handleDragStart =
|
|
12889
|
+
const handleDragStart = React29__namespace.useCallback((e) => {
|
|
11665
12890
|
if (disabled) return;
|
|
11666
12891
|
e.dataTransfer.effectAllowed = "move";
|
|
11667
12892
|
e.dataTransfer.setData("text/plain", event.id);
|
|
11668
12893
|
setDraggedEvent(event);
|
|
11669
12894
|
}, [disabled, event, setDraggedEvent]);
|
|
11670
|
-
const handleDragEnd =
|
|
12895
|
+
const handleDragEnd = React29__namespace.useCallback(() => {
|
|
11671
12896
|
setDraggedEvent(null);
|
|
11672
12897
|
}, [setDraggedEvent]);
|
|
11673
12898
|
return {
|
|
@@ -11708,15 +12933,15 @@ function MonthView({
|
|
|
11708
12933
|
}) {
|
|
11709
12934
|
const { selectedDate, badgeVariant, setSelectedDate, setView } = useEventCalendar();
|
|
11710
12935
|
const filteredEvents = useFilteredEvents();
|
|
11711
|
-
const { singleDayEvents, multiDayEvents } =
|
|
12936
|
+
const { singleDayEvents, multiDayEvents } = React29__namespace.useMemo(
|
|
11712
12937
|
() => splitEventsByDuration(filteredEvents),
|
|
11713
12938
|
[filteredEvents]
|
|
11714
12939
|
);
|
|
11715
|
-
const cells =
|
|
12940
|
+
const cells = React29__namespace.useMemo(
|
|
11716
12941
|
() => getCalendarCells(selectedDate),
|
|
11717
12942
|
[selectedDate]
|
|
11718
12943
|
);
|
|
11719
|
-
const eventPositions =
|
|
12944
|
+
const eventPositions = React29__namespace.useMemo(
|
|
11720
12945
|
() => calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate),
|
|
11721
12946
|
[multiDayEvents, singleDayEvents, selectedDate]
|
|
11722
12947
|
);
|
|
@@ -11898,7 +13123,7 @@ function WeekView({
|
|
|
11898
13123
|
visibleHours
|
|
11899
13124
|
} = useEventCalendar();
|
|
11900
13125
|
const filteredEvents = useFilteredEvents();
|
|
11901
|
-
const { singleDayEvents, multiDayEvents } =
|
|
13126
|
+
const { singleDayEvents, multiDayEvents } = React29__namespace.useMemo(
|
|
11902
13127
|
() => splitEventsByDuration(filteredEvents),
|
|
11903
13128
|
[filteredEvents]
|
|
11904
13129
|
);
|
|
@@ -12104,8 +13329,8 @@ function CalendarTimeline({
|
|
|
12104
13329
|
firstVisibleHour,
|
|
12105
13330
|
lastVisibleHour
|
|
12106
13331
|
}) {
|
|
12107
|
-
const [currentTime, setCurrentTime] =
|
|
12108
|
-
|
|
13332
|
+
const [currentTime, setCurrentTime] = React29__namespace.useState(/* @__PURE__ */ new Date());
|
|
13333
|
+
React29__namespace.useEffect(() => {
|
|
12109
13334
|
const interval = setInterval(() => {
|
|
12110
13335
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
12111
13336
|
}, 6e4);
|
|
@@ -12188,7 +13413,7 @@ function DayView({
|
|
|
12188
13413
|
visibleHours
|
|
12189
13414
|
} = useEventCalendar();
|
|
12190
13415
|
const filteredEvents = useFilteredEvents();
|
|
12191
|
-
const { singleDayEvents, multiDayEvents } =
|
|
13416
|
+
const { singleDayEvents, multiDayEvents } = React29__namespace.useMemo(
|
|
12192
13417
|
() => splitEventsByDuration(filteredEvents),
|
|
12193
13418
|
[filteredEvents]
|
|
12194
13419
|
);
|
|
@@ -12196,7 +13421,7 @@ function DayView({
|
|
|
12196
13421
|
visibleHours,
|
|
12197
13422
|
singleDayEvents
|
|
12198
13423
|
);
|
|
12199
|
-
const currentEvents =
|
|
13424
|
+
const currentEvents = React29__namespace.useMemo(() => {
|
|
12200
13425
|
if (!dateFns.isToday(selectedDate)) return [];
|
|
12201
13426
|
return getCurrentEvents(singleDayEvents);
|
|
12202
13427
|
}, [singleDayEvents, selectedDate]);
|
|
@@ -12420,8 +13645,8 @@ function CalendarTimeline2({
|
|
|
12420
13645
|
firstVisibleHour,
|
|
12421
13646
|
lastVisibleHour
|
|
12422
13647
|
}) {
|
|
12423
|
-
const [currentTime, setCurrentTime] =
|
|
12424
|
-
|
|
13648
|
+
const [currentTime, setCurrentTime] = React29__namespace.useState(/* @__PURE__ */ new Date());
|
|
13649
|
+
React29__namespace.useEffect(() => {
|
|
12425
13650
|
const interval = setInterval(() => {
|
|
12426
13651
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
12427
13652
|
}, 6e4);
|
|
@@ -12455,7 +13680,7 @@ function YearView({
|
|
|
12455
13680
|
}) {
|
|
12456
13681
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
12457
13682
|
const filteredEvents = useFilteredEvents();
|
|
12458
|
-
const months =
|
|
13683
|
+
const months = React29__namespace.useMemo(() => {
|
|
12459
13684
|
const yearStart = dateFns.startOfYear(selectedDate);
|
|
12460
13685
|
return Array.from({ length: 12 }, (_, i) => dateFns.addMonths(yearStart, i));
|
|
12461
13686
|
}, [selectedDate]);
|
|
@@ -12578,11 +13803,11 @@ function AgendaView({
|
|
|
12578
13803
|
}) {
|
|
12579
13804
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
12580
13805
|
const filteredEvents = useFilteredEvents();
|
|
12581
|
-
const { singleDayEvents, multiDayEvents } =
|
|
13806
|
+
const { singleDayEvents, multiDayEvents } = React29__namespace.useMemo(
|
|
12582
13807
|
() => splitEventsByDuration(filteredEvents),
|
|
12583
13808
|
[filteredEvents]
|
|
12584
13809
|
);
|
|
12585
|
-
const eventsByDay =
|
|
13810
|
+
const eventsByDay = React29__namespace.useMemo(() => {
|
|
12586
13811
|
const allDates = /* @__PURE__ */ new Map();
|
|
12587
13812
|
singleDayEvents.forEach((event) => {
|
|
12588
13813
|
const eventDate = dateFns.parseISO(event.startDate);
|
|
@@ -13047,16 +14272,16 @@ function EventDialog({
|
|
|
13047
14272
|
defaultUserId
|
|
13048
14273
|
}) {
|
|
13049
14274
|
const { addEvent, updateEvent, deleteEvent, users } = useEventCalendar();
|
|
13050
|
-
const [title, setTitle] =
|
|
13051
|
-
const [description, setDescription] =
|
|
13052
|
-
const [startDate, setStartDate] =
|
|
13053
|
-
const [startTime, setStartTime] =
|
|
13054
|
-
const [endDate, setEndDate] =
|
|
13055
|
-
const [endTime, setEndTime] =
|
|
13056
|
-
const [color, setColor] =
|
|
13057
|
-
const [userId, setUserId] =
|
|
13058
|
-
const [isSubmitting, setIsSubmitting] =
|
|
13059
|
-
|
|
14275
|
+
const [title, setTitle] = React29__namespace.useState("");
|
|
14276
|
+
const [description, setDescription] = React29__namespace.useState("");
|
|
14277
|
+
const [startDate, setStartDate] = React29__namespace.useState("");
|
|
14278
|
+
const [startTime, setStartTime] = React29__namespace.useState("");
|
|
14279
|
+
const [endDate, setEndDate] = React29__namespace.useState("");
|
|
14280
|
+
const [endTime, setEndTime] = React29__namespace.useState("");
|
|
14281
|
+
const [color, setColor] = React29__namespace.useState("blue");
|
|
14282
|
+
const [userId, setUserId] = React29__namespace.useState("");
|
|
14283
|
+
const [isSubmitting, setIsSubmitting] = React29__namespace.useState(false);
|
|
14284
|
+
React29__namespace.useEffect(() => {
|
|
13060
14285
|
if (open) {
|
|
13061
14286
|
if (mode === "edit" && event) {
|
|
13062
14287
|
const start = dateFns.parseISO(event.startDate);
|
|
@@ -13279,7 +14504,7 @@ function QuickAddEvent({
|
|
|
13279
14504
|
onOpenDialog,
|
|
13280
14505
|
onClose
|
|
13281
14506
|
}) {
|
|
13282
|
-
const [title, setTitle] =
|
|
14507
|
+
const [title, setTitle] = React29__namespace.useState("");
|
|
13283
14508
|
const { users } = useEventCalendar();
|
|
13284
14509
|
const handleSubmit = (e) => {
|
|
13285
14510
|
e.preventDefault();
|
|
@@ -13346,8 +14571,8 @@ var HOUR_OPTIONS = Array.from({ length: 25 }, (_, i) => {
|
|
|
13346
14571
|
});
|
|
13347
14572
|
function ChangeVisibleHoursInput() {
|
|
13348
14573
|
const { visibleHours, setVisibleHours } = useEventCalendar();
|
|
13349
|
-
const [from, setFrom] =
|
|
13350
|
-
const [to, setTo] =
|
|
14574
|
+
const [from, setFrom] = React29__namespace.useState(visibleHours.from);
|
|
14575
|
+
const [to, setTo] = React29__namespace.useState(visibleHours.to);
|
|
13351
14576
|
const handleApply = () => {
|
|
13352
14577
|
const toHour = to === 0 ? 24 : to;
|
|
13353
14578
|
setVisibleHours({ from, to: toHour });
|
|
@@ -13393,7 +14618,7 @@ var HOUR_OPTIONS2 = Array.from({ length: 25 }, (_, i) => {
|
|
|
13393
14618
|
});
|
|
13394
14619
|
function ChangeWorkingHoursInput() {
|
|
13395
14620
|
const { workingHours, setWorkingHours } = useEventCalendar();
|
|
13396
|
-
const [localWorkingHours, setLocalWorkingHours] =
|
|
14621
|
+
const [localWorkingHours, setLocalWorkingHours] = React29__namespace.useState({
|
|
13397
14622
|
...workingHours
|
|
13398
14623
|
});
|
|
13399
14624
|
const handleToggleDay = (dayId) => {
|
|
@@ -13542,8 +14767,8 @@ function CalendarSettingsButton({
|
|
|
13542
14767
|
);
|
|
13543
14768
|
}
|
|
13544
14769
|
function useMediaQuery(query) {
|
|
13545
|
-
const [matches, setMatches] =
|
|
13546
|
-
|
|
14770
|
+
const [matches, setMatches] = React29__namespace.useState(false);
|
|
14771
|
+
React29__namespace.useEffect(() => {
|
|
13547
14772
|
const media = window.matchMedia(query);
|
|
13548
14773
|
setMatches(media.matches);
|
|
13549
14774
|
const listener = (event) => {
|
|
@@ -13595,11 +14820,11 @@ function BigCalendarInner({
|
|
|
13595
14820
|
maxEventsPerDay
|
|
13596
14821
|
}) {
|
|
13597
14822
|
const { view, setView } = useEventCalendar();
|
|
13598
|
-
const [dialogOpen, setDialogOpen] =
|
|
13599
|
-
const [settingsDialogOpen, setSettingsDialogOpen] =
|
|
13600
|
-
const [selectedEvent, setSelectedEvent] =
|
|
13601
|
-
const [dialogMode, setDialogMode] =
|
|
13602
|
-
const [defaultDate, setDefaultDate] =
|
|
14823
|
+
const [dialogOpen, setDialogOpen] = React29__namespace.useState(false);
|
|
14824
|
+
const [settingsDialogOpen, setSettingsDialogOpen] = React29__namespace.useState(false);
|
|
14825
|
+
const [selectedEvent, setSelectedEvent] = React29__namespace.useState(null);
|
|
14826
|
+
const [dialogMode, setDialogMode] = React29__namespace.useState("add");
|
|
14827
|
+
const [defaultDate, setDefaultDate] = React29__namespace.useState(/* @__PURE__ */ new Date());
|
|
13603
14828
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
13604
14829
|
const isCompact = compact === "auto" ? isMobile : compact;
|
|
13605
14830
|
const handleAddClick = () => {
|
|
@@ -13886,7 +15111,7 @@ var calculateInnerOffset = (date, range, columnWidth) => {
|
|
|
13886
15111
|
const dayOfMonth = date.getDate();
|
|
13887
15112
|
return dayOfMonth / totalRangeDays * columnWidth;
|
|
13888
15113
|
};
|
|
13889
|
-
var GanttContext =
|
|
15114
|
+
var GanttContext = React29.createContext({
|
|
13890
15115
|
zoom: 100,
|
|
13891
15116
|
range: "monthly",
|
|
13892
15117
|
columnWidth: 50,
|
|
@@ -13907,11 +15132,11 @@ var GanttContentHeader = ({
|
|
|
13907
15132
|
columns,
|
|
13908
15133
|
renderHeaderItem
|
|
13909
15134
|
}) => {
|
|
13910
|
-
const id =
|
|
15135
|
+
const id = React29.useId();
|
|
13911
15136
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13912
15137
|
"div",
|
|
13913
15138
|
{
|
|
13914
|
-
className: "sticky top-0 z-20 grid w-full shrink-0 bg-
|
|
15139
|
+
className: "sticky top-0 z-20 grid w-full shrink-0 bg-muted/80 backdrop-blur-sm",
|
|
13915
15140
|
style: { height: "var(--gantt-header-height)" },
|
|
13916
15141
|
children: [
|
|
13917
15142
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13955,8 +15180,8 @@ var getWeekStartDate = (year, weekNumber) => {
|
|
|
13955
15180
|
return dateFns.addWeeks(week1Start, weekNumber - 1);
|
|
13956
15181
|
};
|
|
13957
15182
|
var WeeklyHeader = () => {
|
|
13958
|
-
const gantt =
|
|
13959
|
-
const weeklyData =
|
|
15183
|
+
const gantt = React29.useContext(GanttContext);
|
|
15184
|
+
const weeklyData = React29.useMemo(() => {
|
|
13960
15185
|
const result = [];
|
|
13961
15186
|
for (const yearData of gantt.timelineData) {
|
|
13962
15187
|
const year = yearData.year;
|
|
@@ -13991,7 +15216,7 @@ var WeeklyHeader = () => {
|
|
|
13991
15216
|
] }, yearData.year));
|
|
13992
15217
|
};
|
|
13993
15218
|
var MonthlyHeader = () => {
|
|
13994
|
-
const gantt =
|
|
15219
|
+
const gantt = React29.useContext(GanttContext);
|
|
13995
15220
|
return gantt.timelineData.map((year) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col", children: [
|
|
13996
15221
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13997
15222
|
GanttContentHeader,
|
|
@@ -14010,7 +15235,7 @@ var MonthlyHeader = () => {
|
|
|
14010
15235
|
] }, year.year));
|
|
14011
15236
|
};
|
|
14012
15237
|
var QuarterlyHeader = () => {
|
|
14013
|
-
const gantt =
|
|
15238
|
+
const gantt = React29.useContext(GanttContext);
|
|
14014
15239
|
return gantt.timelineData.map(
|
|
14015
15240
|
(year) => year.quarters.map((quarter, quarterIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14016
15241
|
"div",
|
|
@@ -14038,7 +15263,7 @@ var headers = {
|
|
|
14038
15263
|
quarterly: QuarterlyHeader
|
|
14039
15264
|
};
|
|
14040
15265
|
var GanttHeader = ({ className }) => {
|
|
14041
|
-
const gantt =
|
|
15266
|
+
const gantt = React29.useContext(GanttContext);
|
|
14042
15267
|
const Header2 = headers[gantt.range];
|
|
14043
15268
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14044
15269
|
"div",
|
|
@@ -14056,7 +15281,7 @@ var GanttSidebarItem = ({
|
|
|
14056
15281
|
onSelectItem,
|
|
14057
15282
|
className
|
|
14058
15283
|
}) => {
|
|
14059
|
-
const gantt =
|
|
15284
|
+
const gantt = React29.useContext(GanttContext);
|
|
14060
15285
|
const tempEndAt = feature.endAt && dateFns.isSameDay(feature.startAt, feature.endAt) ? dateFns.addDays(feature.endAt, 1) : feature.endAt;
|
|
14061
15286
|
const duration = tempEndAt ? dateFns.formatDistance(feature.startAt, tempEndAt) : `${dateFns.formatDistance(feature.startAt, /* @__PURE__ */ new Date())} so far`;
|
|
14062
15287
|
const handleClick = (event) => {
|
|
@@ -14108,7 +15333,7 @@ var GanttSidebarHeader = ({
|
|
|
14108
15333
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14109
15334
|
"div",
|
|
14110
15335
|
{
|
|
14111
|
-
className: "sticky top-0 z-
|
|
15336
|
+
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
15337
|
style: { height: "var(--gantt-header-height)" },
|
|
14113
15338
|
children: [
|
|
14114
15339
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex-1 truncate text-left", children: title }),
|
|
@@ -14132,24 +15357,24 @@ function computeGroupRange(features) {
|
|
|
14132
15357
|
}
|
|
14133
15358
|
return { start: minStart, end: maxEnd };
|
|
14134
15359
|
}
|
|
14135
|
-
var GanttGroupSummaryBar =
|
|
15360
|
+
var GanttGroupSummaryBar = React29.memo(({
|
|
14136
15361
|
group,
|
|
14137
15362
|
className
|
|
14138
15363
|
}) => {
|
|
14139
|
-
const gantt =
|
|
14140
|
-
const timelineStartDate =
|
|
15364
|
+
const gantt = React29.useContext(GanttContext);
|
|
15365
|
+
const timelineStartDate = React29.useMemo(
|
|
14141
15366
|
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14142
15367
|
[gantt.timelineData]
|
|
14143
15368
|
);
|
|
14144
|
-
const { start: groupStart, end: groupEnd } =
|
|
15369
|
+
const { start: groupStart, end: groupEnd } = React29.useMemo(
|
|
14145
15370
|
() => computeGroupRange(group.features),
|
|
14146
15371
|
[group.features]
|
|
14147
15372
|
);
|
|
14148
|
-
const offset =
|
|
15373
|
+
const offset = React29.useMemo(() => {
|
|
14149
15374
|
if (!groupStart) return 0;
|
|
14150
15375
|
return Math.round(getOffset(groupStart, timelineStartDate, gantt));
|
|
14151
15376
|
}, [groupStart, timelineStartDate, gantt]);
|
|
14152
|
-
const width =
|
|
15377
|
+
const width = React29.useMemo(() => {
|
|
14153
15378
|
if (!groupStart || !groupEnd) return 0;
|
|
14154
15379
|
return Math.round(getWidth(groupStart, groupEnd, gantt));
|
|
14155
15380
|
}, [groupStart, groupEnd, gantt]);
|
|
@@ -14172,11 +15397,12 @@ var GanttGroupSummaryBar = React27.memo(({
|
|
|
14172
15397
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14173
15398
|
"div",
|
|
14174
15399
|
{
|
|
14175
|
-
className: "h-full w-full rounded-sm border border-border/60 bg-muted/40 shadow-sm",
|
|
15400
|
+
className: "relative h-full w-full rounded-sm border border-border/60 bg-muted/40 shadow-sm overflow-hidden",
|
|
14176
15401
|
style: {
|
|
14177
15402
|
// Subtle gradient for depth
|
|
14178
15403
|
background: "linear-gradient(180deg, hsl(var(--muted) / 0.5) 0%, hsl(var(--muted) / 0.3) 100%)"
|
|
14179
|
-
}
|
|
15404
|
+
},
|
|
15405
|
+
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
15406
|
}
|
|
14181
15407
|
)
|
|
14182
15408
|
}
|
|
@@ -14188,13 +15414,13 @@ var GanttCollapsibleSidebarGroup = ({
|
|
|
14188
15414
|
children,
|
|
14189
15415
|
className
|
|
14190
15416
|
}) => {
|
|
14191
|
-
const gantt =
|
|
15417
|
+
const gantt = React29.useContext(GanttContext);
|
|
14192
15418
|
const isExpanded = gantt.expandedGroups[group.id] ?? true;
|
|
14193
|
-
const { start: groupStart, end: groupEnd } =
|
|
15419
|
+
const { start: groupStart, end: groupEnd } = React29.useMemo(
|
|
14194
15420
|
() => computeGroupRange(group.features),
|
|
14195
15421
|
[group.features]
|
|
14196
15422
|
);
|
|
14197
|
-
const duration =
|
|
15423
|
+
const duration = React29.useMemo(() => {
|
|
14198
15424
|
if (!groupStart || !groupEnd) return null;
|
|
14199
15425
|
return dateFns.formatDistance(groupStart, groupEnd);
|
|
14200
15426
|
}, [groupStart, groupEnd]);
|
|
@@ -14208,7 +15434,7 @@ var GanttCollapsibleSidebarGroup = ({
|
|
|
14208
15434
|
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14209
15435
|
"button",
|
|
14210
15436
|
{
|
|
14211
|
-
className: "flex w-full items-center gap-2 px-2.5 py-2 text-left font-medium text-xs hover:bg-muted/
|
|
15437
|
+
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
15438
|
style: { height: "var(--gantt-row-height)" },
|
|
14213
15439
|
type: "button",
|
|
14214
15440
|
children: [
|
|
@@ -14238,7 +15464,7 @@ var GanttCollapsibleTimelineGroup = ({
|
|
|
14238
15464
|
children,
|
|
14239
15465
|
className
|
|
14240
15466
|
}) => {
|
|
14241
|
-
const gantt =
|
|
15467
|
+
const gantt = React29.useContext(GanttContext);
|
|
14242
15468
|
const isExpanded = gantt.expandedGroups[group.id] ?? true;
|
|
14243
15469
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14244
15470
|
Collapsible,
|
|
@@ -14250,7 +15476,7 @@ var GanttCollapsibleTimelineGroup = ({
|
|
|
14250
15476
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14251
15477
|
"div",
|
|
14252
15478
|
{
|
|
14253
|
-
className: "relative w-full border-b border-border/50",
|
|
15479
|
+
className: "relative w-full border-b border-border/50 bg-muted/20",
|
|
14254
15480
|
style: { height: "var(--gantt-row-height)" },
|
|
14255
15481
|
children: /* @__PURE__ */ jsxRuntime.jsx(GanttGroupSummaryBar, { group })
|
|
14256
15482
|
}
|
|
@@ -14268,7 +15494,7 @@ var GanttSidebarGroup = ({
|
|
|
14268
15494
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14269
15495
|
"p",
|
|
14270
15496
|
{
|
|
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-
|
|
15497
|
+
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
15498
|
style: { height: "var(--gantt-row-height)" },
|
|
14273
15499
|
children: name
|
|
14274
15500
|
}
|
|
@@ -14282,7 +15508,7 @@ var GanttSidebar = ({
|
|
|
14282
15508
|
"div",
|
|
14283
15509
|
{
|
|
14284
15510
|
className: cn(
|
|
14285
|
-
"sticky left-0 z-30 h-max min-h-full border-border/50 border-r bg-
|
|
15511
|
+
"sticky left-0 z-30 h-max min-h-full border-border/50 border-r bg-muted/50",
|
|
14286
15512
|
className
|
|
14287
15513
|
),
|
|
14288
15514
|
style: { width: "var(--gantt-sidebar-width)" },
|
|
@@ -14298,7 +15524,7 @@ var GanttAddFeatureHelper = ({
|
|
|
14298
15524
|
className
|
|
14299
15525
|
}) => {
|
|
14300
15526
|
const [scrollX] = useGanttScrollX();
|
|
14301
|
-
const gantt =
|
|
15527
|
+
const gantt = React29.useContext(GanttContext);
|
|
14302
15528
|
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14303
15529
|
const handleClick = () => {
|
|
14304
15530
|
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
@@ -14337,10 +15563,10 @@ var GanttColumn = ({
|
|
|
14337
15563
|
index,
|
|
14338
15564
|
isColumnSecondary
|
|
14339
15565
|
}) => {
|
|
14340
|
-
const gantt =
|
|
15566
|
+
const gantt = React29.useContext(GanttContext);
|
|
14341
15567
|
const [dragging] = useGanttDragging();
|
|
14342
15568
|
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14343
|
-
const [hovering, setHovering] =
|
|
15569
|
+
const [hovering, setHovering] = React29.useState(false);
|
|
14344
15570
|
const [windowScroll] = usehooks.useWindowScroll();
|
|
14345
15571
|
const handleMouseEnter = () => setHovering(true);
|
|
14346
15572
|
const handleMouseLeave = () => setHovering(false);
|
|
@@ -14370,7 +15596,7 @@ var GanttColumns = ({
|
|
|
14370
15596
|
columns,
|
|
14371
15597
|
isColumnSecondary
|
|
14372
15598
|
}) => {
|
|
14373
|
-
const id =
|
|
15599
|
+
const id = React29.useId();
|
|
14374
15600
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14375
15601
|
"div",
|
|
14376
15602
|
{
|
|
@@ -14389,12 +15615,12 @@ var GanttColumns = ({
|
|
|
14389
15615
|
}
|
|
14390
15616
|
);
|
|
14391
15617
|
};
|
|
14392
|
-
var GanttGridLines =
|
|
15618
|
+
var GanttGridLines = React29.memo(({
|
|
14393
15619
|
className
|
|
14394
15620
|
}) => {
|
|
14395
|
-
const gantt =
|
|
14396
|
-
const id =
|
|
14397
|
-
const { columns, monthBoundaryIndices } =
|
|
15621
|
+
const gantt = React29.useContext(GanttContext);
|
|
15622
|
+
const id = React29.useId();
|
|
15623
|
+
const { columns, monthBoundaryIndices } = React29.useMemo(() => {
|
|
14398
15624
|
let totalColumns = 0;
|
|
14399
15625
|
const monthIndices = [];
|
|
14400
15626
|
if (gantt.range === "weekly") {
|
|
@@ -14458,7 +15684,7 @@ var GanttCreateMarkerTrigger = ({
|
|
|
14458
15684
|
onCreateMarker,
|
|
14459
15685
|
className
|
|
14460
15686
|
}) => {
|
|
14461
|
-
const gantt =
|
|
15687
|
+
const gantt = React29.useContext(GanttContext);
|
|
14462
15688
|
const [mousePosition, mouseRef] = usehooks.useMouse();
|
|
14463
15689
|
const [windowScroll] = usehooks.useWindowScroll();
|
|
14464
15690
|
const x = usehooks.useThrottle(
|
|
@@ -14507,7 +15733,7 @@ var GanttFeatureDragHelper = ({
|
|
|
14507
15733
|
id: `feature-drag-helper-${featureId}`
|
|
14508
15734
|
});
|
|
14509
15735
|
const isPressed = Boolean(attributes["aria-pressed"]);
|
|
14510
|
-
|
|
15736
|
+
React29.useEffect(() => setDragging(isPressed), [isPressed, setDragging]);
|
|
14511
15737
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14512
15738
|
"div",
|
|
14513
15739
|
{
|
|
@@ -14553,7 +15779,7 @@ var GanttFeatureItemCard = ({
|
|
|
14553
15779
|
const [, setDragging] = useGanttDragging();
|
|
14554
15780
|
const { attributes, listeners, setNodeRef } = core.useDraggable({ id });
|
|
14555
15781
|
const isPressed = Boolean(attributes["aria-pressed"]);
|
|
14556
|
-
|
|
15782
|
+
React29.useEffect(() => setDragging(isPressed), [isPressed, setDragging]);
|
|
14557
15783
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "h-full w-full rounded-sm border bg-background px-2 py-1.5 text-xs shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14558
15784
|
"div",
|
|
14559
15785
|
{
|
|
@@ -14579,37 +15805,37 @@ var GanttFeatureItem = ({
|
|
|
14579
15805
|
...feature
|
|
14580
15806
|
}) => {
|
|
14581
15807
|
const [scrollX] = useGanttScrollX();
|
|
14582
|
-
const gantt =
|
|
14583
|
-
const timelineStartDate =
|
|
15808
|
+
const gantt = React29.useContext(GanttContext);
|
|
15809
|
+
const timelineStartDate = React29.useMemo(
|
|
14584
15810
|
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14585
15811
|
[gantt.timelineData]
|
|
14586
15812
|
);
|
|
14587
|
-
const [startAt, setStartAt] =
|
|
14588
|
-
const [endAt, setEndAt] =
|
|
14589
|
-
const width =
|
|
15813
|
+
const [startAt, setStartAt] = React29.useState(feature.startAt);
|
|
15814
|
+
const [endAt, setEndAt] = React29.useState(feature.endAt);
|
|
15815
|
+
const width = React29.useMemo(
|
|
14590
15816
|
() => Math.round(getWidth(startAt, endAt, gantt)),
|
|
14591
15817
|
[startAt, endAt, gantt]
|
|
14592
15818
|
);
|
|
14593
|
-
const offset =
|
|
15819
|
+
const offset = React29.useMemo(
|
|
14594
15820
|
() => Math.round(getOffset(startAt, timelineStartDate, gantt)),
|
|
14595
15821
|
[startAt, timelineStartDate, gantt]
|
|
14596
15822
|
);
|
|
14597
|
-
const addRange =
|
|
15823
|
+
const addRange = React29.useMemo(() => getAddRange(gantt.range), [gantt.range]);
|
|
14598
15824
|
const [mousePosition] = usehooks.useMouse();
|
|
14599
|
-
const [previousMouseX, setPreviousMouseX] =
|
|
14600
|
-
const [previousStartAt, setPreviousStartAt] =
|
|
14601
|
-
const [previousEndAt, setPreviousEndAt] =
|
|
15825
|
+
const [previousMouseX, setPreviousMouseX] = React29.useState(0);
|
|
15826
|
+
const [previousStartAt, setPreviousStartAt] = React29.useState(startAt);
|
|
15827
|
+
const [previousEndAt, setPreviousEndAt] = React29.useState(endAt);
|
|
14602
15828
|
const mouseSensor = core.useSensor(core.MouseSensor, {
|
|
14603
15829
|
activationConstraint: {
|
|
14604
15830
|
distance: 10
|
|
14605
15831
|
}
|
|
14606
15832
|
});
|
|
14607
|
-
const handleItemDragStart =
|
|
15833
|
+
const handleItemDragStart = React29.useCallback(() => {
|
|
14608
15834
|
setPreviousMouseX(mousePosition.x);
|
|
14609
15835
|
setPreviousStartAt(startAt);
|
|
14610
15836
|
setPreviousEndAt(endAt);
|
|
14611
15837
|
}, [mousePosition.x, startAt, endAt]);
|
|
14612
|
-
const handleItemDragMove =
|
|
15838
|
+
const handleItemDragMove = React29.useCallback(() => {
|
|
14613
15839
|
const currentDate = getDateByMousePosition(gantt, mousePosition.x);
|
|
14614
15840
|
const originalDate = getDateByMousePosition(gantt, previousMouseX);
|
|
14615
15841
|
const delta = gantt.range === "weekly" ? dateFns.differenceInDays(currentDate, originalDate) : getInnerDifferenceIn(gantt.range)(currentDate, originalDate);
|
|
@@ -14618,17 +15844,17 @@ var GanttFeatureItem = ({
|
|
|
14618
15844
|
setStartAt(newStartDate);
|
|
14619
15845
|
setEndAt(newEndDate);
|
|
14620
15846
|
}, [gantt, mousePosition.x, previousMouseX, previousStartAt, previousEndAt]);
|
|
14621
|
-
const onDragEnd =
|
|
15847
|
+
const onDragEnd = React29.useCallback(
|
|
14622
15848
|
() => onMove?.(feature.id, startAt, endAt),
|
|
14623
15849
|
[onMove, feature.id, startAt, endAt]
|
|
14624
15850
|
);
|
|
14625
|
-
const handleLeftDragMove =
|
|
15851
|
+
const handleLeftDragMove = React29.useCallback(() => {
|
|
14626
15852
|
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
14627
15853
|
const x = mousePosition.x - (ganttRect?.left ?? 0) + scrollX - gantt.sidebarWidth;
|
|
14628
15854
|
const newStartAt = getDateByMousePosition(gantt, x);
|
|
14629
15855
|
setStartAt(newStartAt);
|
|
14630
15856
|
}, [gantt, mousePosition.x, scrollX]);
|
|
14631
|
-
const handleRightDragMove =
|
|
15857
|
+
const handleRightDragMove = React29.useCallback(() => {
|
|
14632
15858
|
const ganttRect = gantt.ref?.current?.getBoundingClientRect();
|
|
14633
15859
|
const x = mousePosition.x - (ganttRect?.left ?? 0) + scrollX - gantt.sidebarWidth;
|
|
14634
15860
|
const newEndAt = getDateByMousePosition(gantt, x);
|
|
@@ -14824,21 +16050,21 @@ var GanttFeatureList = ({
|
|
|
14824
16050
|
children
|
|
14825
16051
|
}
|
|
14826
16052
|
);
|
|
14827
|
-
var GanttMarker =
|
|
14828
|
-
const gantt =
|
|
14829
|
-
const differenceIn =
|
|
16053
|
+
var GanttMarker = React29.memo(({ label, date, id, onRemove, className }) => {
|
|
16054
|
+
const gantt = React29.useContext(GanttContext);
|
|
16055
|
+
const differenceIn = React29.useMemo(
|
|
14830
16056
|
() => getDifferenceIn(gantt.range),
|
|
14831
16057
|
[gantt.range]
|
|
14832
16058
|
);
|
|
14833
|
-
const timelineStartDate =
|
|
16059
|
+
const timelineStartDate = React29.useMemo(
|
|
14834
16060
|
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
14835
16061
|
[gantt.timelineData]
|
|
14836
16062
|
);
|
|
14837
|
-
const offset =
|
|
16063
|
+
const offset = React29.useMemo(
|
|
14838
16064
|
() => differenceIn(date, timelineStartDate),
|
|
14839
16065
|
[differenceIn, date, timelineStartDate]
|
|
14840
16066
|
);
|
|
14841
|
-
const innerOffset =
|
|
16067
|
+
const innerOffset = React29.useMemo(
|
|
14842
16068
|
() => calculateInnerOffset(
|
|
14843
16069
|
date,
|
|
14844
16070
|
gantt.range,
|
|
@@ -14846,7 +16072,7 @@ var GanttMarker = React27.memo(({ label, date, id, onRemove, className }) => {
|
|
|
14846
16072
|
),
|
|
14847
16073
|
[date, gantt.range, gantt.columnWidth, gantt.zoom]
|
|
14848
16074
|
);
|
|
14849
|
-
const handleRemove =
|
|
16075
|
+
const handleRemove = React29.useCallback(() => onRemove?.(id), [onRemove, id]);
|
|
14850
16076
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14851
16077
|
"div",
|
|
14852
16078
|
{
|
|
@@ -14896,14 +16122,14 @@ var GanttProvider = ({
|
|
|
14896
16122
|
className,
|
|
14897
16123
|
defaultExpandedGroups = {}
|
|
14898
16124
|
}) => {
|
|
14899
|
-
const scrollRef =
|
|
14900
|
-
const [timelineData, setTimelineData] =
|
|
16125
|
+
const scrollRef = React29.useRef(null);
|
|
16126
|
+
const [timelineData, setTimelineData] = React29.useState(
|
|
14901
16127
|
createInitialTimelineData(/* @__PURE__ */ new Date())
|
|
14902
16128
|
);
|
|
14903
16129
|
const [, setScrollX] = useGanttScrollX();
|
|
14904
16130
|
const sidebarWidth = 280;
|
|
14905
|
-
const [expandedGroups, setExpandedGroups] =
|
|
14906
|
-
const setGroupExpanded =
|
|
16131
|
+
const [expandedGroups, setExpandedGroups] = React29.useState(defaultExpandedGroups);
|
|
16132
|
+
const setGroupExpanded = React29.useCallback((groupId, expanded) => {
|
|
14907
16133
|
setExpandedGroups((prev) => ({ ...prev, [groupId]: expanded }));
|
|
14908
16134
|
}, []);
|
|
14909
16135
|
const headerHeight = 60;
|
|
@@ -14914,7 +16140,7 @@ var GanttProvider = ({
|
|
|
14914
16140
|
} else if (range === "quarterly") {
|
|
14915
16141
|
columnWidth = 100;
|
|
14916
16142
|
}
|
|
14917
|
-
const cssVariables =
|
|
16143
|
+
const cssVariables = React29.useMemo(
|
|
14918
16144
|
() => ({
|
|
14919
16145
|
"--gantt-zoom": `${zoom}`,
|
|
14920
16146
|
"--gantt-column-width": `${zoom / 100 * columnWidth}px`,
|
|
@@ -14924,13 +16150,13 @@ var GanttProvider = ({
|
|
|
14924
16150
|
}),
|
|
14925
16151
|
[zoom, columnWidth, sidebarWidth]
|
|
14926
16152
|
);
|
|
14927
|
-
|
|
16153
|
+
React29.useEffect(() => {
|
|
14928
16154
|
if (scrollRef.current) {
|
|
14929
16155
|
scrollRef.current.scrollLeft = scrollRef.current.scrollWidth / 2 - scrollRef.current.clientWidth / 2;
|
|
14930
16156
|
setScrollX(scrollRef.current.scrollLeft);
|
|
14931
16157
|
}
|
|
14932
16158
|
}, [setScrollX]);
|
|
14933
|
-
const handleScroll =
|
|
16159
|
+
const handleScroll = React29.useCallback(
|
|
14934
16160
|
throttle__default.default(() => {
|
|
14935
16161
|
const scrollElement = scrollRef.current;
|
|
14936
16162
|
if (!scrollElement) {
|
|
@@ -14982,7 +16208,7 @@ var GanttProvider = ({
|
|
|
14982
16208
|
}, 100),
|
|
14983
16209
|
[]
|
|
14984
16210
|
);
|
|
14985
|
-
|
|
16211
|
+
React29.useEffect(() => {
|
|
14986
16212
|
const scrollElement = scrollRef.current;
|
|
14987
16213
|
if (scrollElement) {
|
|
14988
16214
|
scrollElement.addEventListener("scroll", handleScroll);
|
|
@@ -14993,7 +16219,7 @@ var GanttProvider = ({
|
|
|
14993
16219
|
}
|
|
14994
16220
|
};
|
|
14995
16221
|
}, [handleScroll]);
|
|
14996
|
-
const scrollToFeature =
|
|
16222
|
+
const scrollToFeature = React29.useCallback(
|
|
14997
16223
|
(feature) => {
|
|
14998
16224
|
const scrollElement = scrollRef.current;
|
|
14999
16225
|
if (!scrollElement) {
|
|
@@ -15073,21 +16299,21 @@ var GanttTimeline = ({
|
|
|
15073
16299
|
);
|
|
15074
16300
|
var GanttToday = ({ className }) => {
|
|
15075
16301
|
const label = "Today";
|
|
15076
|
-
const date =
|
|
15077
|
-
const gantt =
|
|
15078
|
-
const differenceIn =
|
|
16302
|
+
const date = React29.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
16303
|
+
const gantt = React29.useContext(GanttContext);
|
|
16304
|
+
const differenceIn = React29.useMemo(
|
|
15079
16305
|
() => getDifferenceIn(gantt.range),
|
|
15080
16306
|
[gantt.range]
|
|
15081
16307
|
);
|
|
15082
|
-
const timelineStartDate =
|
|
16308
|
+
const timelineStartDate = React29.useMemo(
|
|
15083
16309
|
() => new Date(gantt.timelineData.at(0)?.year ?? 0, 0, 1),
|
|
15084
16310
|
[gantt.timelineData]
|
|
15085
16311
|
);
|
|
15086
|
-
const offset =
|
|
16312
|
+
const offset = React29.useMemo(
|
|
15087
16313
|
() => differenceIn(date, timelineStartDate),
|
|
15088
16314
|
[differenceIn, date, timelineStartDate]
|
|
15089
16315
|
);
|
|
15090
|
-
const innerOffset =
|
|
16316
|
+
const innerOffset = React29.useMemo(
|
|
15091
16317
|
() => Math.round(calculateInnerOffset(
|
|
15092
16318
|
date,
|
|
15093
16319
|
gantt.range,
|
|
@@ -15123,7 +16349,7 @@ var GanttToday = ({ className }) => {
|
|
|
15123
16349
|
);
|
|
15124
16350
|
};
|
|
15125
16351
|
var t = tunnel__default.default();
|
|
15126
|
-
var KanbanContext =
|
|
16352
|
+
var KanbanContext = React29.createContext({
|
|
15127
16353
|
columns: [],
|
|
15128
16354
|
data: [],
|
|
15129
16355
|
activeCardId: null
|
|
@@ -15161,7 +16387,7 @@ var KanbanCard = ({
|
|
|
15161
16387
|
} = sortable.useSortable({
|
|
15162
16388
|
id
|
|
15163
16389
|
});
|
|
15164
|
-
const { activeCardId } =
|
|
16390
|
+
const { activeCardId } = React29.useContext(KanbanContext);
|
|
15165
16391
|
const style = {
|
|
15166
16392
|
transition,
|
|
15167
16393
|
transform: utilities.CSS.Transform.toString(transform)
|
|
@@ -15196,7 +16422,7 @@ var KanbanCards = ({
|
|
|
15196
16422
|
className,
|
|
15197
16423
|
...props
|
|
15198
16424
|
}) => {
|
|
15199
|
-
const { data } =
|
|
16425
|
+
const { data } = React29.useContext(KanbanContext);
|
|
15200
16426
|
const filteredData = data.filter((item) => item.column === props.id);
|
|
15201
16427
|
const items = filteredData.map((item) => item.id);
|
|
15202
16428
|
return /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "overflow-hidden", children: [
|
|
@@ -15223,7 +16449,7 @@ var KanbanProvider = ({
|
|
|
15223
16449
|
onDataChange,
|
|
15224
16450
|
...props
|
|
15225
16451
|
}) => {
|
|
15226
|
-
const [activeCardId, setActiveCardId] =
|
|
16452
|
+
const [activeCardId, setActiveCardId] = React29.useState(null);
|
|
15227
16453
|
const sensors = core.useSensors(
|
|
15228
16454
|
core.useSensor(core.MouseSensor),
|
|
15229
16455
|
core.useSensor(core.TouchSensor),
|
|
@@ -15732,6 +16958,7 @@ exports.SiteHeader = SiteHeader;
|
|
|
15732
16958
|
exports.Skeleton = Skeleton;
|
|
15733
16959
|
exports.Slider = Slider;
|
|
15734
16960
|
exports.Spinner = Spinner;
|
|
16961
|
+
exports.StatusProgress = StatusProgress;
|
|
15735
16962
|
exports.SubmitCalibrationBar = SubmitCalibrationBar;
|
|
15736
16963
|
exports.SupplierCell = SupplierCell;
|
|
15737
16964
|
exports.SupplierWeeklyLoading = SupplierWeeklyLoading;
|
|
@@ -15767,6 +16994,7 @@ exports.UserAvatarsDropdown = UserAvatarsDropdown;
|
|
|
15767
16994
|
exports.VIEW_LABELS = VIEW_LABELS;
|
|
15768
16995
|
exports.WeekCell = WeekCell;
|
|
15769
16996
|
exports.WeekDetailDialog = WeekDetailDialog;
|
|
16997
|
+
exports.WeekDetailSheet = WeekDetailSheet;
|
|
15770
16998
|
exports.WeekHeader = WeekHeader;
|
|
15771
16999
|
exports.WeekView = WeekView;
|
|
15772
17000
|
exports.WeeklyLoadingView = WeeklyLoadingView;
|