@j3m-quantum/ui 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3643 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +897 -1
- package/dist/index.d.ts +897 -1
- package/dist/index.js +3462 -190
- package/dist/index.js.map +1 -1
- package/dist/styles/generated/variables.css +1 -3
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React22 = 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');
|
|
@@ -40,6 +40,7 @@ var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
|
40
40
|
var HoverCardPrimitive = require('@radix-ui/react-hover-card');
|
|
41
41
|
var CollapsiblePrimitive = require('@radix-ui/react-collapsible');
|
|
42
42
|
var ResizablePrimitive = require('react-resizable-panels');
|
|
43
|
+
var reactTable = require('@tanstack/react-table');
|
|
43
44
|
var dateFns = require('date-fns');
|
|
44
45
|
|
|
45
46
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -62,7 +63,7 @@ function _interopNamespace(e) {
|
|
|
62
63
|
return Object.freeze(n);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
var
|
|
66
|
+
var React22__namespace = /*#__PURE__*/_interopNamespace(React22);
|
|
66
67
|
var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
|
|
67
68
|
var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
|
|
68
69
|
var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
|
|
@@ -95,8 +96,8 @@ var ResizablePrimitive__namespace = /*#__PURE__*/_interopNamespace(ResizablePrim
|
|
|
95
96
|
// src/hooks/use-mobile.ts
|
|
96
97
|
var MOBILE_BREAKPOINT = 768;
|
|
97
98
|
function useIsMobile() {
|
|
98
|
-
const [isMobile, setIsMobile] =
|
|
99
|
-
|
|
99
|
+
const [isMobile, setIsMobile] = React22__namespace.useState(void 0);
|
|
100
|
+
React22__namespace.useEffect(() => {
|
|
100
101
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
101
102
|
const onChange = () => {
|
|
102
103
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -137,7 +138,7 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
);
|
|
140
|
-
var Button =
|
|
141
|
+
var Button = React22__namespace.forwardRef(
|
|
141
142
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
142
143
|
const Comp = asChild ? reactSlot.Slot : "button";
|
|
143
144
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -501,7 +502,7 @@ function Slider({
|
|
|
501
502
|
max = 100,
|
|
502
503
|
...props
|
|
503
504
|
}) {
|
|
504
|
-
const _values =
|
|
505
|
+
const _values = React22__namespace.useMemo(
|
|
505
506
|
() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
|
|
506
507
|
[value, defaultValue, min, max]
|
|
507
508
|
);
|
|
@@ -787,7 +788,7 @@ function Toggle({
|
|
|
787
788
|
}
|
|
788
789
|
);
|
|
789
790
|
}
|
|
790
|
-
var ToggleGroupContext =
|
|
791
|
+
var ToggleGroupContext = React22__namespace.createContext({
|
|
791
792
|
size: "default",
|
|
792
793
|
variant: "default",
|
|
793
794
|
spacing: 0
|
|
@@ -824,7 +825,7 @@ function ToggleGroupItem({
|
|
|
824
825
|
size,
|
|
825
826
|
...props
|
|
826
827
|
}) {
|
|
827
|
-
const context =
|
|
828
|
+
const context = React22__namespace.useContext(ToggleGroupContext);
|
|
828
829
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
829
830
|
ToggleGroupPrimitive__namespace.Item,
|
|
830
831
|
{
|
|
@@ -854,7 +855,7 @@ function ThemeSwitch({
|
|
|
854
855
|
className,
|
|
855
856
|
size = "default"
|
|
856
857
|
}) {
|
|
857
|
-
const [isChecked, setIsChecked] =
|
|
858
|
+
const [isChecked, setIsChecked] = React22__namespace.useState(defaultChecked);
|
|
858
859
|
const isControlled = checked !== void 0;
|
|
859
860
|
const currentChecked = isControlled ? checked : isChecked;
|
|
860
861
|
const handleClick = () => {
|
|
@@ -1274,7 +1275,7 @@ function Label2({
|
|
|
1274
1275
|
);
|
|
1275
1276
|
}
|
|
1276
1277
|
var Form = reactHookForm.FormProvider;
|
|
1277
|
-
var FormFieldContext =
|
|
1278
|
+
var FormFieldContext = React22__namespace.createContext(
|
|
1278
1279
|
{}
|
|
1279
1280
|
);
|
|
1280
1281
|
var FormField = ({
|
|
@@ -1283,8 +1284,8 @@ var FormField = ({
|
|
|
1283
1284
|
return /* @__PURE__ */ jsxRuntime.jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.Controller, { ...props }) });
|
|
1284
1285
|
};
|
|
1285
1286
|
var useFormField = () => {
|
|
1286
|
-
const fieldContext =
|
|
1287
|
-
const itemContext =
|
|
1287
|
+
const fieldContext = React22__namespace.useContext(FormFieldContext);
|
|
1288
|
+
const itemContext = React22__namespace.useContext(FormItemContext);
|
|
1288
1289
|
const { getFieldState } = reactHookForm.useFormContext();
|
|
1289
1290
|
const formState = reactHookForm.useFormState({ name: fieldContext.name });
|
|
1290
1291
|
const fieldState = getFieldState(fieldContext.name, formState);
|
|
@@ -1301,11 +1302,11 @@ var useFormField = () => {
|
|
|
1301
1302
|
...fieldState
|
|
1302
1303
|
};
|
|
1303
1304
|
};
|
|
1304
|
-
var FormItemContext =
|
|
1305
|
+
var FormItemContext = React22__namespace.createContext(
|
|
1305
1306
|
{}
|
|
1306
1307
|
);
|
|
1307
1308
|
function FormItem({ className, ...props }) {
|
|
1308
|
-
const id =
|
|
1309
|
+
const id = React22__namespace.useId();
|
|
1309
1310
|
return /* @__PURE__ */ jsxRuntime.jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1310
1311
|
"div",
|
|
1311
1312
|
{
|
|
@@ -1553,7 +1554,7 @@ function FieldError({
|
|
|
1553
1554
|
errors,
|
|
1554
1555
|
...props
|
|
1555
1556
|
}) {
|
|
1556
|
-
const content =
|
|
1557
|
+
const content = React22.useMemo(() => {
|
|
1557
1558
|
if (children) {
|
|
1558
1559
|
return children;
|
|
1559
1560
|
}
|
|
@@ -2407,8 +2408,8 @@ function CalendarDayButton({
|
|
|
2407
2408
|
modifiers,
|
|
2408
2409
|
...props
|
|
2409
2410
|
}) {
|
|
2410
|
-
const ref =
|
|
2411
|
-
|
|
2411
|
+
const ref = React22__namespace.useRef(null);
|
|
2412
|
+
React22__namespace.useEffect(() => {
|
|
2412
2413
|
if (modifiers.focused) ref.current?.focus();
|
|
2413
2414
|
}, [modifiers.focused]);
|
|
2414
2415
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2429,9 +2430,9 @@ function CalendarDayButton({
|
|
|
2429
2430
|
}
|
|
2430
2431
|
);
|
|
2431
2432
|
}
|
|
2432
|
-
var CarouselContext =
|
|
2433
|
+
var CarouselContext = React22__namespace.createContext(null);
|
|
2433
2434
|
function useCarousel() {
|
|
2434
|
-
const context =
|
|
2435
|
+
const context = React22__namespace.useContext(CarouselContext);
|
|
2435
2436
|
if (!context) {
|
|
2436
2437
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
2437
2438
|
}
|
|
@@ -2453,20 +2454,20 @@ function Carousel({
|
|
|
2453
2454
|
},
|
|
2454
2455
|
plugins
|
|
2455
2456
|
);
|
|
2456
|
-
const [canScrollPrev, setCanScrollPrev] =
|
|
2457
|
-
const [canScrollNext, setCanScrollNext] =
|
|
2458
|
-
const onSelect =
|
|
2457
|
+
const [canScrollPrev, setCanScrollPrev] = React22__namespace.useState(false);
|
|
2458
|
+
const [canScrollNext, setCanScrollNext] = React22__namespace.useState(false);
|
|
2459
|
+
const onSelect = React22__namespace.useCallback((api2) => {
|
|
2459
2460
|
if (!api2) return;
|
|
2460
2461
|
setCanScrollPrev(api2.canScrollPrev());
|
|
2461
2462
|
setCanScrollNext(api2.canScrollNext());
|
|
2462
2463
|
}, []);
|
|
2463
|
-
const scrollPrev =
|
|
2464
|
+
const scrollPrev = React22__namespace.useCallback(() => {
|
|
2464
2465
|
api?.scrollPrev();
|
|
2465
2466
|
}, [api]);
|
|
2466
|
-
const scrollNext =
|
|
2467
|
+
const scrollNext = React22__namespace.useCallback(() => {
|
|
2467
2468
|
api?.scrollNext();
|
|
2468
2469
|
}, [api]);
|
|
2469
|
-
const handleKeyDown =
|
|
2470
|
+
const handleKeyDown = React22__namespace.useCallback(
|
|
2470
2471
|
(event) => {
|
|
2471
2472
|
if (event.key === "ArrowLeft") {
|
|
2472
2473
|
event.preventDefault();
|
|
@@ -2478,11 +2479,11 @@ function Carousel({
|
|
|
2478
2479
|
},
|
|
2479
2480
|
[scrollPrev, scrollNext]
|
|
2480
2481
|
);
|
|
2481
|
-
|
|
2482
|
+
React22__namespace.useEffect(() => {
|
|
2482
2483
|
if (!api || !setApi) return;
|
|
2483
2484
|
setApi(api);
|
|
2484
2485
|
}, [api, setApi]);
|
|
2485
|
-
|
|
2486
|
+
React22__namespace.useEffect(() => {
|
|
2486
2487
|
if (!api) return;
|
|
2487
2488
|
onSelect(api);
|
|
2488
2489
|
api.on("reInit", onSelect);
|
|
@@ -2615,9 +2616,9 @@ function CarouselNext({
|
|
|
2615
2616
|
);
|
|
2616
2617
|
}
|
|
2617
2618
|
var THEMES = { light: "", dark: ".dark" };
|
|
2618
|
-
var ChartContext =
|
|
2619
|
+
var ChartContext = React22__namespace.createContext(null);
|
|
2619
2620
|
function useChart() {
|
|
2620
|
-
const context =
|
|
2621
|
+
const context = React22__namespace.useContext(ChartContext);
|
|
2621
2622
|
if (!context) {
|
|
2622
2623
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
2623
2624
|
}
|
|
@@ -2630,7 +2631,7 @@ function ChartContainer({
|
|
|
2630
2631
|
config,
|
|
2631
2632
|
...props
|
|
2632
2633
|
}) {
|
|
2633
|
-
const uniqueId =
|
|
2634
|
+
const uniqueId = React22__namespace.useId();
|
|
2634
2635
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
2635
2636
|
return /* @__PURE__ */ jsxRuntime.jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2636
2637
|
"div",
|
|
@@ -2691,7 +2692,7 @@ function ChartTooltipContent({
|
|
|
2691
2692
|
labelKey
|
|
2692
2693
|
}) {
|
|
2693
2694
|
const { config } = useChart();
|
|
2694
|
-
const tooltipLabel =
|
|
2695
|
+
const tooltipLabel = React22__namespace.useMemo(() => {
|
|
2695
2696
|
if (hideLabel || !payload?.length) {
|
|
2696
2697
|
return null;
|
|
2697
2698
|
}
|
|
@@ -3347,6 +3348,105 @@ function Progress({
|
|
|
3347
3348
|
}
|
|
3348
3349
|
);
|
|
3349
3350
|
}
|
|
3351
|
+
function CircularProgress({
|
|
3352
|
+
className,
|
|
3353
|
+
value,
|
|
3354
|
+
size = 80,
|
|
3355
|
+
strokeWidth = 8,
|
|
3356
|
+
variant = "default",
|
|
3357
|
+
showCheckmark = true,
|
|
3358
|
+
children,
|
|
3359
|
+
...props
|
|
3360
|
+
}) {
|
|
3361
|
+
const clampedValue = Math.min(100, Math.max(0, value));
|
|
3362
|
+
const isComplete = clampedValue >= 100;
|
|
3363
|
+
const radius = (size - strokeWidth) / 2;
|
|
3364
|
+
const circumference = 2 * Math.PI * radius;
|
|
3365
|
+
const strokeDashoffset = circumference - clampedValue / 100 * circumference;
|
|
3366
|
+
const center = size / 2;
|
|
3367
|
+
const getVariantColors = () => {
|
|
3368
|
+
switch (variant) {
|
|
3369
|
+
case "success":
|
|
3370
|
+
return {
|
|
3371
|
+
track: "stroke-green-500/20",
|
|
3372
|
+
progress: "stroke-green-500",
|
|
3373
|
+
text: "text-green-600 dark:text-green-400"
|
|
3374
|
+
};
|
|
3375
|
+
case "warning":
|
|
3376
|
+
return {
|
|
3377
|
+
track: "stroke-amber-500/20",
|
|
3378
|
+
progress: "stroke-amber-500",
|
|
3379
|
+
text: "text-amber-600 dark:text-amber-400"
|
|
3380
|
+
};
|
|
3381
|
+
case "destructive":
|
|
3382
|
+
return {
|
|
3383
|
+
track: "stroke-red-500/20",
|
|
3384
|
+
progress: "stroke-red-500",
|
|
3385
|
+
text: "text-red-600 dark:text-red-400"
|
|
3386
|
+
};
|
|
3387
|
+
default:
|
|
3388
|
+
return {
|
|
3389
|
+
track: "stroke-primary/20",
|
|
3390
|
+
progress: "stroke-primary",
|
|
3391
|
+
text: "text-primary"
|
|
3392
|
+
};
|
|
3393
|
+
}
|
|
3394
|
+
};
|
|
3395
|
+
const colors = getVariantColors();
|
|
3396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3397
|
+
"div",
|
|
3398
|
+
{
|
|
3399
|
+
"data-slot": "circular-progress",
|
|
3400
|
+
"data-value": clampedValue,
|
|
3401
|
+
"data-complete": isComplete,
|
|
3402
|
+
className: cn("relative inline-flex items-center justify-center", className),
|
|
3403
|
+
style: { width: size, height: size },
|
|
3404
|
+
...props,
|
|
3405
|
+
children: [
|
|
3406
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3407
|
+
"svg",
|
|
3408
|
+
{
|
|
3409
|
+
className: "transform -rotate-90",
|
|
3410
|
+
width: size,
|
|
3411
|
+
height: size,
|
|
3412
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
3413
|
+
children: [
|
|
3414
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3415
|
+
"circle",
|
|
3416
|
+
{
|
|
3417
|
+
className: cn("transition-all", colors.track),
|
|
3418
|
+
cx: center,
|
|
3419
|
+
cy: center,
|
|
3420
|
+
r: radius,
|
|
3421
|
+
fill: "none",
|
|
3422
|
+
strokeWidth
|
|
3423
|
+
}
|
|
3424
|
+
),
|
|
3425
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3426
|
+
"circle",
|
|
3427
|
+
{
|
|
3428
|
+
className: cn("transition-all duration-300 ease-out", colors.progress),
|
|
3429
|
+
cx: center,
|
|
3430
|
+
cy: center,
|
|
3431
|
+
r: radius,
|
|
3432
|
+
fill: "none",
|
|
3433
|
+
strokeWidth,
|
|
3434
|
+
strokeLinecap: "round",
|
|
3435
|
+
strokeDasharray: circumference,
|
|
3436
|
+
strokeDashoffset
|
|
3437
|
+
}
|
|
3438
|
+
)
|
|
3439
|
+
]
|
|
3440
|
+
}
|
|
3441
|
+
),
|
|
3442
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: children ? children : isComplete && showCheckmark ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-6 w-6", colors.text) }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-sm font-semibold tabular-nums", colors.text), children: [
|
|
3443
|
+
Math.round(clampedValue),
|
|
3444
|
+
"%"
|
|
3445
|
+
] }) })
|
|
3446
|
+
]
|
|
3447
|
+
}
|
|
3448
|
+
);
|
|
3449
|
+
}
|
|
3350
3450
|
function TooltipProvider({
|
|
3351
3451
|
delayDuration = 0,
|
|
3352
3452
|
...props
|
|
@@ -3394,8 +3494,8 @@ function TooltipContent({
|
|
|
3394
3494
|
) });
|
|
3395
3495
|
}
|
|
3396
3496
|
function useDetectTheme() {
|
|
3397
|
-
const [theme, setTheme] =
|
|
3398
|
-
|
|
3497
|
+
const [theme, setTheme] = React22__namespace.useState("light");
|
|
3498
|
+
React22__namespace.useEffect(() => {
|
|
3399
3499
|
const isDark = document.documentElement.classList.contains("dark");
|
|
3400
3500
|
setTheme(isDark ? "dark" : "light");
|
|
3401
3501
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -3447,6 +3547,81 @@ function Spinner({ className, ...props }) {
|
|
|
3447
3547
|
}
|
|
3448
3548
|
);
|
|
3449
3549
|
}
|
|
3550
|
+
var deliveryIndicatorVariants = classVarianceAuthority.cva(
|
|
3551
|
+
"inline-block rounded-full shrink-0",
|
|
3552
|
+
{
|
|
3553
|
+
variants: {
|
|
3554
|
+
status: {
|
|
3555
|
+
"on-time": "bg-[var(--j3m-green-9,#84EBB4)]",
|
|
3556
|
+
"delayed": "bg-[var(--j3m-yellow-9,#FFDB43)]",
|
|
3557
|
+
"critical": "bg-[var(--j3m-red-9,#FB3748)]",
|
|
3558
|
+
"pending": "bg-[var(--j3m-gray-6,#D2D2D2)]"
|
|
3559
|
+
},
|
|
3560
|
+
size: {
|
|
3561
|
+
sm: "h-1.5 w-3",
|
|
3562
|
+
default: "h-1.5 w-3",
|
|
3563
|
+
lg: "h-2 w-4"
|
|
3564
|
+
}
|
|
3565
|
+
},
|
|
3566
|
+
defaultVariants: {
|
|
3567
|
+
status: "pending",
|
|
3568
|
+
size: "default"
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
);
|
|
3572
|
+
function DeliveryIndicator({
|
|
3573
|
+
className,
|
|
3574
|
+
status,
|
|
3575
|
+
size,
|
|
3576
|
+
label,
|
|
3577
|
+
showTooltip = false,
|
|
3578
|
+
...props
|
|
3579
|
+
}) {
|
|
3580
|
+
const indicator = /* @__PURE__ */ jsxRuntime.jsx(
|
|
3581
|
+
"span",
|
|
3582
|
+
{
|
|
3583
|
+
"data-slot": "delivery-indicator",
|
|
3584
|
+
"data-status": status,
|
|
3585
|
+
className: cn(deliveryIndicatorVariants({ status, size }), className),
|
|
3586
|
+
"aria-label": label || `Delivery status: ${status}`,
|
|
3587
|
+
role: "img",
|
|
3588
|
+
...props
|
|
3589
|
+
}
|
|
3590
|
+
);
|
|
3591
|
+
if (showTooltip && label) {
|
|
3592
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip2, { children: [
|
|
3593
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: indicator }),
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: label })
|
|
3595
|
+
] });
|
|
3596
|
+
}
|
|
3597
|
+
return indicator;
|
|
3598
|
+
}
|
|
3599
|
+
function DeliveryIndicators({
|
|
3600
|
+
className,
|
|
3601
|
+
deliveries,
|
|
3602
|
+
size = "default",
|
|
3603
|
+
showTooltips = false,
|
|
3604
|
+
...props
|
|
3605
|
+
}) {
|
|
3606
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3607
|
+
"div",
|
|
3608
|
+
{
|
|
3609
|
+
"data-slot": "delivery-indicators",
|
|
3610
|
+
className: cn("flex items-center gap-1", className),
|
|
3611
|
+
...props,
|
|
3612
|
+
children: deliveries.map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3613
|
+
DeliveryIndicator,
|
|
3614
|
+
{
|
|
3615
|
+
status: delivery.status,
|
|
3616
|
+
size,
|
|
3617
|
+
label: delivery.label,
|
|
3618
|
+
showTooltip: showTooltips
|
|
3619
|
+
},
|
|
3620
|
+
index
|
|
3621
|
+
))
|
|
3622
|
+
}
|
|
3623
|
+
);
|
|
3624
|
+
}
|
|
3450
3625
|
function Breadcrumb({ ...props }) {
|
|
3451
3626
|
return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "breadcrumb", "data-slot": "breadcrumb", ...props });
|
|
3452
3627
|
}
|
|
@@ -3969,7 +4144,7 @@ function CommandShortcut({
|
|
|
3969
4144
|
}
|
|
3970
4145
|
);
|
|
3971
4146
|
}
|
|
3972
|
-
var SearchTrigger =
|
|
4147
|
+
var SearchTrigger = React22__namespace.forwardRef(
|
|
3973
4148
|
({
|
|
3974
4149
|
className,
|
|
3975
4150
|
placeholder = "Search...",
|
|
@@ -4005,7 +4180,7 @@ var SearchTrigger = React15__namespace.forwardRef(
|
|
|
4005
4180
|
);
|
|
4006
4181
|
SearchTrigger.displayName = "SearchTrigger";
|
|
4007
4182
|
function useSearchShortcut(onOpen, key = "k") {
|
|
4008
|
-
|
|
4183
|
+
React22__namespace.useEffect(() => {
|
|
4009
4184
|
const down = (e) => {
|
|
4010
4185
|
if (e.key.toLowerCase() === key.toLowerCase() && (e.metaKey || e.ctrlKey)) {
|
|
4011
4186
|
e.preventDefault();
|
|
@@ -4980,9 +5155,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
4980
5155
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
4981
5156
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
4982
5157
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
4983
|
-
var SidebarContext =
|
|
5158
|
+
var SidebarContext = React22__namespace.createContext(null);
|
|
4984
5159
|
function useSidebar() {
|
|
4985
|
-
const context =
|
|
5160
|
+
const context = React22__namespace.useContext(SidebarContext);
|
|
4986
5161
|
if (!context) {
|
|
4987
5162
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
4988
5163
|
}
|
|
@@ -4998,10 +5173,10 @@ function SidebarProvider({
|
|
|
4998
5173
|
...props
|
|
4999
5174
|
}) {
|
|
5000
5175
|
const isMobile = useIsMobile();
|
|
5001
|
-
const [openMobile, setOpenMobile] =
|
|
5002
|
-
const [_open, _setOpen] =
|
|
5176
|
+
const [openMobile, setOpenMobile] = React22__namespace.useState(false);
|
|
5177
|
+
const [_open, _setOpen] = React22__namespace.useState(defaultOpen);
|
|
5003
5178
|
const open = openProp ?? _open;
|
|
5004
|
-
const setOpen =
|
|
5179
|
+
const setOpen = React22__namespace.useCallback(
|
|
5005
5180
|
(value) => {
|
|
5006
5181
|
const openState = typeof value === "function" ? value(open) : value;
|
|
5007
5182
|
if (setOpenProp) {
|
|
@@ -5013,10 +5188,10 @@ function SidebarProvider({
|
|
|
5013
5188
|
},
|
|
5014
5189
|
[setOpenProp, open]
|
|
5015
5190
|
);
|
|
5016
|
-
const toggleSidebar =
|
|
5191
|
+
const toggleSidebar = React22__namespace.useCallback(() => {
|
|
5017
5192
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
5018
5193
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
5019
|
-
|
|
5194
|
+
React22__namespace.useEffect(() => {
|
|
5020
5195
|
const handleKeyDown = (event) => {
|
|
5021
5196
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
5022
5197
|
event.preventDefault();
|
|
@@ -5027,7 +5202,7 @@ function SidebarProvider({
|
|
|
5027
5202
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
5028
5203
|
}, [toggleSidebar]);
|
|
5029
5204
|
const state = open ? "expanded" : "collapsed";
|
|
5030
|
-
const contextValue =
|
|
5205
|
+
const contextValue = React22__namespace.useMemo(
|
|
5031
5206
|
() => ({
|
|
5032
5207
|
state,
|
|
5033
5208
|
open,
|
|
@@ -5485,7 +5660,7 @@ function SidebarMenuSkeleton({
|
|
|
5485
5660
|
showIcon = false,
|
|
5486
5661
|
...props
|
|
5487
5662
|
}) {
|
|
5488
|
-
const width =
|
|
5663
|
+
const width = React22__namespace.useMemo(() => {
|
|
5489
5664
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
5490
5665
|
}, []);
|
|
5491
5666
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -5628,7 +5803,7 @@ var sectionVariants = classVarianceAuthority.cva(
|
|
|
5628
5803
|
}
|
|
5629
5804
|
);
|
|
5630
5805
|
var isGlassVariant = (variant) => variant?.startsWith("glass-") ?? false;
|
|
5631
|
-
var Section =
|
|
5806
|
+
var Section = React22__namespace.forwardRef(
|
|
5632
5807
|
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5633
5808
|
"section",
|
|
5634
5809
|
{
|
|
@@ -5640,7 +5815,7 @@ var Section = React15__namespace.forwardRef(
|
|
|
5640
5815
|
)
|
|
5641
5816
|
);
|
|
5642
5817
|
Section.displayName = "Section";
|
|
5643
|
-
var SectionHeader =
|
|
5818
|
+
var SectionHeader = React22__namespace.forwardRef(
|
|
5644
5819
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5645
5820
|
"div",
|
|
5646
5821
|
{
|
|
@@ -5655,7 +5830,7 @@ var SectionHeader = React15__namespace.forwardRef(
|
|
|
5655
5830
|
)
|
|
5656
5831
|
);
|
|
5657
5832
|
SectionHeader.displayName = "SectionHeader";
|
|
5658
|
-
var SectionTitle =
|
|
5833
|
+
var SectionTitle = React22__namespace.forwardRef(
|
|
5659
5834
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5660
5835
|
"h2",
|
|
5661
5836
|
{
|
|
@@ -5669,7 +5844,7 @@ var SectionTitle = React15__namespace.forwardRef(
|
|
|
5669
5844
|
)
|
|
5670
5845
|
);
|
|
5671
5846
|
SectionTitle.displayName = "SectionTitle";
|
|
5672
|
-
var SectionDescription =
|
|
5847
|
+
var SectionDescription = React22__namespace.forwardRef(
|
|
5673
5848
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5674
5849
|
"p",
|
|
5675
5850
|
{
|
|
@@ -5683,219 +5858,3315 @@ var SectionDescription = React15__namespace.forwardRef(
|
|
|
5683
5858
|
)
|
|
5684
5859
|
);
|
|
5685
5860
|
SectionDescription.displayName = "SectionDescription";
|
|
5686
|
-
var SectionContent =
|
|
5861
|
+
var SectionContent = React22__namespace.forwardRef(
|
|
5862
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5863
|
+
"div",
|
|
5864
|
+
{
|
|
5865
|
+
ref,
|
|
5866
|
+
className: cn(
|
|
5867
|
+
"px-[var(--j3m-spacing-xl)] py-[var(--j3m-spacing-l)]",
|
|
5868
|
+
className
|
|
5869
|
+
),
|
|
5870
|
+
...props
|
|
5871
|
+
}
|
|
5872
|
+
)
|
|
5873
|
+
);
|
|
5874
|
+
SectionContent.displayName = "SectionContent";
|
|
5875
|
+
var SectionFooter = React22__namespace.forwardRef(
|
|
5687
5876
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5688
5877
|
"div",
|
|
5689
5878
|
{
|
|
5690
5879
|
ref,
|
|
5691
5880
|
className: cn(
|
|
5881
|
+
"flex items-center",
|
|
5692
5882
|
"px-[var(--j3m-spacing-xl)] py-[var(--j3m-spacing-l)]",
|
|
5883
|
+
"border-t border-[inherit]",
|
|
5693
5884
|
className
|
|
5694
5885
|
),
|
|
5695
5886
|
...props
|
|
5696
5887
|
}
|
|
5697
|
-
)
|
|
5698
|
-
);
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5888
|
+
)
|
|
5889
|
+
);
|
|
5890
|
+
SectionFooter.displayName = "SectionFooter";
|
|
5891
|
+
function DataTableColumnHeader({
|
|
5892
|
+
column,
|
|
5893
|
+
title,
|
|
5894
|
+
className
|
|
5895
|
+
}) {
|
|
5896
|
+
if (!column.getCanSort()) {
|
|
5897
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(className), children: title });
|
|
5898
|
+
}
|
|
5899
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-2", className), children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
5900
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5901
|
+
Button,
|
|
5902
|
+
{
|
|
5903
|
+
variant: "ghost",
|
|
5904
|
+
size: "sm",
|
|
5905
|
+
className: "data-[state=open]:bg-accent -ml-3 h-8",
|
|
5906
|
+
children: [
|
|
5907
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
|
|
5908
|
+
column.getIsSorted() === "desc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, {}) : column.getIsSorted() === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, {})
|
|
5909
|
+
]
|
|
5910
|
+
}
|
|
5911
|
+
) }),
|
|
5912
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "start", children: [
|
|
5913
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => column.toggleSorting(false), children: [
|
|
5914
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, {}),
|
|
5915
|
+
"Asc"
|
|
5916
|
+
] }),
|
|
5917
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => column.toggleSorting(true), children: [
|
|
5918
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, {}),
|
|
5919
|
+
"Desc"
|
|
5920
|
+
] }),
|
|
5921
|
+
column.getCanHide() && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5922
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
5923
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => column.toggleVisibility(false), children: [
|
|
5924
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}),
|
|
5925
|
+
"Hide"
|
|
5926
|
+
] })
|
|
5927
|
+
] })
|
|
5928
|
+
] })
|
|
5929
|
+
] }) });
|
|
5930
|
+
}
|
|
5931
|
+
function DataTablePagination({
|
|
5932
|
+
table,
|
|
5933
|
+
showRowSelection = true,
|
|
5934
|
+
pageSizeOptions = [10, 20, 25, 30, 40, 50]
|
|
5935
|
+
}) {
|
|
5936
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-2", children: [
|
|
5937
|
+
showRowSelection && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-muted-foreground flex-1 text-sm", children: [
|
|
5938
|
+
table.getFilteredSelectedRowModel().rows.length,
|
|
5939
|
+
" of",
|
|
5940
|
+
" ",
|
|
5941
|
+
table.getFilteredRowModel().rows.length,
|
|
5942
|
+
" row(s) selected."
|
|
5943
|
+
] }),
|
|
5944
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-6 lg:space-x-8", children: [
|
|
5945
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
5946
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Rows per page" }),
|
|
5947
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5948
|
+
Select,
|
|
5949
|
+
{
|
|
5950
|
+
value: `${table.getState().pagination.pageSize}`,
|
|
5951
|
+
onValueChange: (value) => {
|
|
5952
|
+
table.setPageSize(Number(value));
|
|
5953
|
+
},
|
|
5954
|
+
children: [
|
|
5955
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "h-8 w-[70px]", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: table.getState().pagination.pageSize }) }),
|
|
5956
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { side: "top", children: pageSizeOptions.map((pageSize) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: `${pageSize}`, children: pageSize }, pageSize)) })
|
|
5957
|
+
]
|
|
5958
|
+
}
|
|
5959
|
+
)
|
|
5960
|
+
] }),
|
|
5961
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[100px] items-center justify-center text-sm font-medium", children: [
|
|
5962
|
+
"Page ",
|
|
5963
|
+
table.getState().pagination.pageIndex + 1,
|
|
5964
|
+
" of",
|
|
5965
|
+
" ",
|
|
5966
|
+
table.getPageCount()
|
|
5967
|
+
] }),
|
|
5968
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
5969
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5970
|
+
Button,
|
|
5971
|
+
{
|
|
5972
|
+
variant: "outline",
|
|
5973
|
+
size: "icon",
|
|
5974
|
+
className: "hidden size-8 lg:flex",
|
|
5975
|
+
onClick: () => table.setPageIndex(0),
|
|
5976
|
+
disabled: !table.getCanPreviousPage(),
|
|
5977
|
+
children: [
|
|
5978
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Go to first page" }),
|
|
5979
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeft, {})
|
|
5980
|
+
]
|
|
5981
|
+
}
|
|
5982
|
+
),
|
|
5983
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5984
|
+
Button,
|
|
5985
|
+
{
|
|
5986
|
+
variant: "outline",
|
|
5987
|
+
size: "icon",
|
|
5988
|
+
className: "size-8",
|
|
5989
|
+
onClick: () => table.previousPage(),
|
|
5990
|
+
disabled: !table.getCanPreviousPage(),
|
|
5991
|
+
children: [
|
|
5992
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Go to previous page" }),
|
|
5993
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, {})
|
|
5994
|
+
]
|
|
5995
|
+
}
|
|
5996
|
+
),
|
|
5997
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5998
|
+
Button,
|
|
5999
|
+
{
|
|
6000
|
+
variant: "outline",
|
|
6001
|
+
size: "icon",
|
|
6002
|
+
className: "size-8",
|
|
6003
|
+
onClick: () => table.nextPage(),
|
|
6004
|
+
disabled: !table.getCanNextPage(),
|
|
6005
|
+
children: [
|
|
6006
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Go to next page" }),
|
|
6007
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, {})
|
|
6008
|
+
]
|
|
6009
|
+
}
|
|
6010
|
+
),
|
|
6011
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6012
|
+
Button,
|
|
6013
|
+
{
|
|
6014
|
+
variant: "outline",
|
|
6015
|
+
size: "icon",
|
|
6016
|
+
className: "hidden size-8 lg:flex",
|
|
6017
|
+
onClick: () => table.setPageIndex(table.getPageCount() - 1),
|
|
6018
|
+
disabled: !table.getCanNextPage(),
|
|
6019
|
+
children: [
|
|
6020
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Go to last page" }),
|
|
6021
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRight, {})
|
|
6022
|
+
]
|
|
6023
|
+
}
|
|
6024
|
+
)
|
|
6025
|
+
] })
|
|
6026
|
+
] })
|
|
6027
|
+
] });
|
|
6028
|
+
}
|
|
6029
|
+
function DataTableViewOptions({
|
|
6030
|
+
table
|
|
6031
|
+
}) {
|
|
6032
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
6033
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6034
|
+
Button,
|
|
6035
|
+
{
|
|
6036
|
+
variant: "outline",
|
|
6037
|
+
size: "sm",
|
|
6038
|
+
className: "ml-auto hidden h-8 lg:flex",
|
|
6039
|
+
children: [
|
|
6040
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, {}),
|
|
6041
|
+
"View"
|
|
6042
|
+
]
|
|
6043
|
+
}
|
|
6044
|
+
) }),
|
|
6045
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-[150px]", children: [
|
|
6046
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuLabel, { children: "Toggle columns" }),
|
|
6047
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
6048
|
+
table.getAllColumns().filter(
|
|
6049
|
+
(column) => typeof column.accessorFn !== "undefined" && column.getCanHide()
|
|
6050
|
+
).map((column) => {
|
|
6051
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6052
|
+
DropdownMenuCheckboxItem,
|
|
6053
|
+
{
|
|
6054
|
+
className: "capitalize",
|
|
6055
|
+
checked: column.getIsVisible(),
|
|
6056
|
+
onCheckedChange: (value) => column.toggleVisibility(!!value),
|
|
6057
|
+
children: column.id
|
|
6058
|
+
},
|
|
6059
|
+
column.id
|
|
6060
|
+
);
|
|
6061
|
+
})
|
|
6062
|
+
] })
|
|
6063
|
+
] });
|
|
6064
|
+
}
|
|
6065
|
+
function SearchForm({ ...props }) {
|
|
6066
|
+
return /* @__PURE__ */ jsxRuntime.jsx("form", { ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
6067
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "search", className: "sr-only", children: "Search" }),
|
|
6068
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6069
|
+
SidebarInput,
|
|
6070
|
+
{
|
|
6071
|
+
id: "search",
|
|
6072
|
+
placeholder: "Type to search...",
|
|
6073
|
+
className: "h-8 pl-7"
|
|
6074
|
+
}
|
|
6075
|
+
),
|
|
6076
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 opacity-50 select-none" })
|
|
6077
|
+
] }) });
|
|
6078
|
+
}
|
|
6079
|
+
function SiteHeader({
|
|
6080
|
+
trigger,
|
|
6081
|
+
breadcrumbs = [
|
|
6082
|
+
{ label: "Building Your Application", href: "#" },
|
|
6083
|
+
{ label: "Data Fetching" }
|
|
6084
|
+
],
|
|
6085
|
+
showSearch = true,
|
|
6086
|
+
className,
|
|
6087
|
+
children
|
|
6088
|
+
}) {
|
|
6089
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6090
|
+
"header",
|
|
6091
|
+
{
|
|
6092
|
+
"data-slot": "site-header",
|
|
6093
|
+
className: cn(
|
|
6094
|
+
"bg-sidebar text-sidebar-foreground sticky top-0 z-50 flex w-full items-center border-b border-sidebar-border",
|
|
6095
|
+
className
|
|
6096
|
+
),
|
|
6097
|
+
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: [
|
|
6098
|
+
trigger,
|
|
6099
|
+
trigger && /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "mr-[var(--j3m-spacing-s)] h-4" }),
|
|
6100
|
+
/* @__PURE__ */ jsxRuntime.jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(React22__namespace.Fragment, { children: [
|
|
6101
|
+
index > 0 && /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbSeparator, {}),
|
|
6102
|
+
/* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { children: item.href ? /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbPage, { children: item.label }) })
|
|
6103
|
+
] }, index)) }) }),
|
|
6104
|
+
showSearch && /* @__PURE__ */ jsxRuntime.jsx(SearchForm, { className: "w-full sm:ml-auto sm:w-auto" }),
|
|
6105
|
+
children
|
|
6106
|
+
] })
|
|
6107
|
+
}
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
function NavMain({ items, label = "Platform" }) {
|
|
6111
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(SidebarGroup, { children: [
|
|
6112
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarGroupLabel, { children: label }),
|
|
6113
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { asChild: true, defaultOpen: item.isActive, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuItem, { children: [
|
|
6114
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, tooltip: item.title, children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
6115
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
6116
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title })
|
|
6117
|
+
] }) }),
|
|
6118
|
+
item.items?.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6119
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuAction, { className: "data-[state=open]:rotate-90", children: [
|
|
6120
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {}),
|
|
6121
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Toggle" })
|
|
6122
|
+
] }) }),
|
|
6123
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSubButton, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: subItem.url, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: subItem.title }) }) }) }, subItem.title)) }) })
|
|
6124
|
+
] }) : null
|
|
6125
|
+
] }) }, item.title)) })
|
|
6126
|
+
] });
|
|
6127
|
+
}
|
|
6128
|
+
function NavProjects({ projects, label = "Projects" }) {
|
|
6129
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(SidebarGroup, { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
6130
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarGroupLabel, { children: label }),
|
|
6131
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SidebarMenu, { children: [
|
|
6132
|
+
projects.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuItem, { children: [
|
|
6133
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
6134
|
+
/* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
6135
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.name })
|
|
6136
|
+
] }) }),
|
|
6137
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
6138
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuAction, { showOnHover: true, children: [
|
|
6139
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontalIcon, {}),
|
|
6140
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "More" })
|
|
6141
|
+
] }) }),
|
|
6142
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6143
|
+
DropdownMenuContent,
|
|
6144
|
+
{
|
|
6145
|
+
className: "w-48 rounded-[var(--j3m-radius-m)]",
|
|
6146
|
+
side: "right",
|
|
6147
|
+
align: "start",
|
|
6148
|
+
sideOffset: 8,
|
|
6149
|
+
children: [
|
|
6150
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6151
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderIcon, { className: "text-muted-foreground" }),
|
|
6152
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "View Project" })
|
|
6153
|
+
] }),
|
|
6154
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6155
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShareIcon, { className: "text-muted-foreground" }),
|
|
6156
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Share Project" })
|
|
6157
|
+
] }),
|
|
6158
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
6159
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6160
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrashIcon, { className: "text-muted-foreground" }),
|
|
6161
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delete Project" })
|
|
6162
|
+
] })
|
|
6163
|
+
]
|
|
6164
|
+
}
|
|
6165
|
+
)
|
|
6166
|
+
] })
|
|
6167
|
+
] }, item.name)),
|
|
6168
|
+
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuButton, { className: "text-sidebar-foreground/70", children: [
|
|
6169
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontalIcon, { className: "text-sidebar-foreground/70" }),
|
|
6170
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "More" })
|
|
6171
|
+
] }) })
|
|
6172
|
+
] })
|
|
6173
|
+
] });
|
|
6174
|
+
}
|
|
6175
|
+
function NavSecondary({ items, ...props }) {
|
|
6176
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SidebarGroup, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
6177
|
+
/* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
6178
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title })
|
|
6179
|
+
] }) }) }, item.title)) }) }) });
|
|
6180
|
+
}
|
|
6181
|
+
function NavUser({ user }) {
|
|
6182
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
6183
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6184
|
+
SidebarMenuButton,
|
|
6185
|
+
{
|
|
6186
|
+
size: "lg",
|
|
6187
|
+
className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
6188
|
+
children: [
|
|
6189
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
6190
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
6191
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
6192
|
+
] }),
|
|
6193
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
6194
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
6195
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
|
|
6196
|
+
] }),
|
|
6197
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDownIcon, { className: "ml-auto size-4" })
|
|
6198
|
+
]
|
|
6199
|
+
}
|
|
6200
|
+
) }),
|
|
6201
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6202
|
+
DropdownMenuContent,
|
|
6203
|
+
{
|
|
6204
|
+
className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-[var(--j3m-radius-m)]",
|
|
6205
|
+
side: "right",
|
|
6206
|
+
align: "end",
|
|
6207
|
+
sideOffset: 8,
|
|
6208
|
+
children: [
|
|
6209
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
|
|
6210
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
6211
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
6212
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
6213
|
+
] }),
|
|
6214
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
6215
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
6216
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
|
|
6217
|
+
] })
|
|
6218
|
+
] }) }),
|
|
6219
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
6220
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6221
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.SparklesIcon, {}),
|
|
6222
|
+
"Upgrade to Pro"
|
|
6223
|
+
] }) }),
|
|
6224
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
6225
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuGroup, { children: [
|
|
6226
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6227
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BadgeCheckIcon, {}),
|
|
6228
|
+
"Account"
|
|
6229
|
+
] }),
|
|
6230
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6231
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCardIcon, {}),
|
|
6232
|
+
"Billing"
|
|
6233
|
+
] }),
|
|
6234
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6235
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BellIcon, {}),
|
|
6236
|
+
"Notifications"
|
|
6237
|
+
] })
|
|
6238
|
+
] }),
|
|
6239
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
6240
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
6241
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOutIcon, {}),
|
|
6242
|
+
"Log out"
|
|
6243
|
+
] })
|
|
6244
|
+
]
|
|
6245
|
+
}
|
|
6246
|
+
)
|
|
6247
|
+
] }) }) });
|
|
6248
|
+
}
|
|
6249
|
+
function PlanningTableToolbar({
|
|
6250
|
+
className,
|
|
6251
|
+
table,
|
|
6252
|
+
...props
|
|
6253
|
+
}) {
|
|
6254
|
+
const isFiltered = table.getState().columnFilters.length > 0;
|
|
6255
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6256
|
+
"div",
|
|
6257
|
+
{
|
|
6258
|
+
"data-slot": "planning-table-toolbar",
|
|
6259
|
+
className: cn("flex items-center gap-2", className),
|
|
6260
|
+
...props,
|
|
6261
|
+
children: [
|
|
6262
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6263
|
+
Input,
|
|
6264
|
+
{
|
|
6265
|
+
placeholder: "Filter suppliers...",
|
|
6266
|
+
value: table.getColumn("supplier")?.getFilterValue() ?? "",
|
|
6267
|
+
onChange: (event) => table.getColumn("supplier")?.setFilterValue(event.target.value),
|
|
6268
|
+
className: "h-8 w-[150px] lg:w-[250px]"
|
|
6269
|
+
}
|
|
6270
|
+
),
|
|
6271
|
+
isFiltered && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6272
|
+
Button,
|
|
6273
|
+
{
|
|
6274
|
+
variant: "ghost",
|
|
6275
|
+
onClick: () => table.resetColumnFilters(),
|
|
6276
|
+
className: "h-8 px-2 lg:px-3",
|
|
6277
|
+
children: [
|
|
6278
|
+
"Reset",
|
|
6279
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "ml-2 h-4 w-4" })
|
|
6280
|
+
]
|
|
6281
|
+
}
|
|
6282
|
+
)
|
|
6283
|
+
]
|
|
6284
|
+
}
|
|
6285
|
+
);
|
|
6286
|
+
}
|
|
6287
|
+
function getBadgeVariant(badgeType) {
|
|
6288
|
+
return "outline";
|
|
6289
|
+
}
|
|
6290
|
+
function SupplierCell({
|
|
6291
|
+
className,
|
|
6292
|
+
supplier,
|
|
6293
|
+
...props
|
|
6294
|
+
}) {
|
|
6295
|
+
const spacingClasses = "px-[var(--j3m-spacing-xs)] pt-[var(--j3m-spacing-s)] pb-2";
|
|
6296
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6297
|
+
"div",
|
|
6298
|
+
{
|
|
6299
|
+
"data-slot": "supplier-cell",
|
|
6300
|
+
className: cn(
|
|
6301
|
+
// Same height as WeekCell (80px) for row alignment
|
|
6302
|
+
"flex flex-col justify-center gap-1.5 min-w-[200px] h-[80px]",
|
|
6303
|
+
// White background for Y-axis legend cells
|
|
6304
|
+
"bg-background",
|
|
6305
|
+
spacingClasses,
|
|
6306
|
+
className
|
|
6307
|
+
),
|
|
6308
|
+
...props,
|
|
6309
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
6310
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
6311
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: supplier.name }),
|
|
6312
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: supplier.scope })
|
|
6313
|
+
] }),
|
|
6314
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6315
|
+
Badge,
|
|
6316
|
+
{
|
|
6317
|
+
variant: getBadgeVariant(supplier.badgeType),
|
|
6318
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
6319
|
+
children: [
|
|
6320
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Flag, { className: "h-2.5 w-2.5" }),
|
|
6321
|
+
supplier.badgeType
|
|
6322
|
+
]
|
|
6323
|
+
}
|
|
6324
|
+
)
|
|
6325
|
+
] })
|
|
6326
|
+
}
|
|
6327
|
+
);
|
|
6328
|
+
}
|
|
6329
|
+
function getCombinedRiskLevel(data) {
|
|
6330
|
+
const productionStatus = data.production?.status || "on-time";
|
|
6331
|
+
const hasDeliveryCritical = data.deliveries?.some((d) => d.status === "critical");
|
|
6332
|
+
const hasDeliveryDelayed = data.deliveries?.some((d) => d.status === "delayed");
|
|
6333
|
+
if (productionStatus === "critical" || hasDeliveryCritical) {
|
|
6334
|
+
return "critical";
|
|
6335
|
+
}
|
|
6336
|
+
if (productionStatus === "delayed" || hasDeliveryDelayed || data.hasWarning) {
|
|
6337
|
+
return "warning";
|
|
6338
|
+
}
|
|
6339
|
+
return "normal";
|
|
6340
|
+
}
|
|
6341
|
+
function getRowStatus(status) {
|
|
6342
|
+
if (status === "critical") return "critical";
|
|
6343
|
+
if (status === "delayed") return "warning";
|
|
6344
|
+
return "normal";
|
|
6345
|
+
}
|
|
6346
|
+
var statusFillClasses = {
|
|
6347
|
+
normal: {
|
|
6348
|
+
border: "border-l-[3px] border-l-green-500",
|
|
6349
|
+
bg: "bg-green-50/50 dark:bg-green-950/30"
|
|
6350
|
+
},
|
|
6351
|
+
warning: {
|
|
6352
|
+
border: "border-l-[3px] border-l-amber-500",
|
|
6353
|
+
bg: "bg-amber-50/50 dark:bg-amber-950/30"
|
|
6354
|
+
},
|
|
6355
|
+
critical: {
|
|
6356
|
+
border: "border-l-[3px] border-l-red-500",
|
|
6357
|
+
bg: "bg-red-50/50 dark:bg-red-950/30"
|
|
6358
|
+
}
|
|
6359
|
+
};
|
|
6360
|
+
var statusColors = {
|
|
6361
|
+
normal: {
|
|
6362
|
+
icon: "text-green-600 dark:text-green-400",
|
|
6363
|
+
progress: "bg-green-500",
|
|
6364
|
+
text: "text-green-700 dark:text-green-300"
|
|
6365
|
+
},
|
|
6366
|
+
warning: {
|
|
6367
|
+
icon: "text-amber-600 dark:text-amber-400",
|
|
6368
|
+
progress: "bg-amber-500",
|
|
6369
|
+
text: "text-amber-700 dark:text-amber-300"
|
|
6370
|
+
},
|
|
6371
|
+
critical: {
|
|
6372
|
+
icon: "text-red-600 dark:text-red-400",
|
|
6373
|
+
progress: "bg-red-500",
|
|
6374
|
+
text: "text-red-700 dark:text-red-300"
|
|
6375
|
+
}
|
|
6376
|
+
};
|
|
6377
|
+
function WeekCell({
|
|
6378
|
+
className,
|
|
6379
|
+
data,
|
|
6380
|
+
week,
|
|
6381
|
+
supplier,
|
|
6382
|
+
isCurrentWeek,
|
|
6383
|
+
onCellClick,
|
|
6384
|
+
...props
|
|
6385
|
+
}) {
|
|
6386
|
+
const combinedRisk = data.type === "data" ? getCombinedRiskLevel(data) : "normal";
|
|
6387
|
+
const statusClasses = statusFillClasses[combinedRisk];
|
|
6388
|
+
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6389
|
+
const productionStatus = getRowStatus(data.production?.status);
|
|
6390
|
+
const productionColors = statusColors[productionStatus];
|
|
6391
|
+
const deliveryCount = data.deliveries?.length ?? 0;
|
|
6392
|
+
const worstDeliveryStatus = data.deliveries?.some((d) => d.status === "critical") ? "critical" : data.deliveries?.some((d) => d.status === "delayed") ? "warning" : "normal";
|
|
6393
|
+
const deliveryColors = statusColors[worstDeliveryStatus];
|
|
6394
|
+
const getDeliveryStatusColor = (status) => {
|
|
6395
|
+
switch (status) {
|
|
6396
|
+
case "critical":
|
|
6397
|
+
return "bg-red-500";
|
|
6398
|
+
case "delayed":
|
|
6399
|
+
return "bg-amber-500";
|
|
6400
|
+
default:
|
|
6401
|
+
return "bg-green-500";
|
|
6402
|
+
}
|
|
6403
|
+
};
|
|
6404
|
+
const handleClick = () => {
|
|
6405
|
+
if (onCellClick && data.type !== "empty") {
|
|
6406
|
+
onCellClick();
|
|
6407
|
+
}
|
|
6408
|
+
};
|
|
6409
|
+
const handleKeyDown = (e) => {
|
|
6410
|
+
if ((e.key === "Enter" || e.key === " ") && onCellClick && data.type !== "empty") {
|
|
6411
|
+
e.preventDefault();
|
|
6412
|
+
onCellClick();
|
|
6413
|
+
}
|
|
6414
|
+
};
|
|
6415
|
+
const spacingClasses = "px-[var(--j3m-spacing-xs)] pt-[var(--j3m-spacing-s)] pb-2";
|
|
6416
|
+
if (data.type === "empty") {
|
|
6417
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6418
|
+
"div",
|
|
6419
|
+
{
|
|
6420
|
+
"data-slot": "week-cell",
|
|
6421
|
+
"data-state": "empty",
|
|
6422
|
+
"data-current-week": isCurrentWeek,
|
|
6423
|
+
className: cn(
|
|
6424
|
+
"flex h-[80px] items-center justify-center cursor-default",
|
|
6425
|
+
"bg-background",
|
|
6426
|
+
spacingClasses,
|
|
6427
|
+
className
|
|
6428
|
+
),
|
|
6429
|
+
...props,
|
|
6430
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/30 text-xl", children: "\xB7" })
|
|
6431
|
+
}
|
|
6432
|
+
);
|
|
6433
|
+
}
|
|
6434
|
+
if (data.type === "no-logistics") {
|
|
6435
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6436
|
+
"div",
|
|
6437
|
+
{
|
|
6438
|
+
"data-slot": "week-cell",
|
|
6439
|
+
"data-state": "no-logistics",
|
|
6440
|
+
"data-current-week": isCurrentWeek,
|
|
6441
|
+
onClick: handleClick,
|
|
6442
|
+
onKeyDown: handleKeyDown,
|
|
6443
|
+
role: "button",
|
|
6444
|
+
tabIndex: 0,
|
|
6445
|
+
className: cn(
|
|
6446
|
+
"flex flex-col h-[80px] justify-center gap-2",
|
|
6447
|
+
"cursor-pointer bg-background",
|
|
6448
|
+
"border-l-[3px] border-l-muted-foreground/30",
|
|
6449
|
+
spacingClasses,
|
|
6450
|
+
// Hover lift effect
|
|
6451
|
+
"transition-all duration-200 ease-out",
|
|
6452
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
6453
|
+
className
|
|
6454
|
+
),
|
|
6455
|
+
...props,
|
|
6456
|
+
children: [
|
|
6457
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6458
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
6459
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-1.5 bg-muted-foreground/20 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6460
|
+
"div",
|
|
6461
|
+
{
|
|
6462
|
+
className: "h-full bg-muted-foreground/40 rounded-full",
|
|
6463
|
+
style: { width: `${productionProgress}%` }
|
|
6464
|
+
}
|
|
6465
|
+
) })
|
|
6466
|
+
] }),
|
|
6467
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
|
|
6468
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
6469
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px]", children: "No logistics" })
|
|
6470
|
+
] })
|
|
6471
|
+
]
|
|
6472
|
+
}
|
|
6473
|
+
);
|
|
6474
|
+
}
|
|
6475
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6476
|
+
"div",
|
|
6477
|
+
{
|
|
6478
|
+
"data-slot": "week-cell",
|
|
6479
|
+
"data-state": "data",
|
|
6480
|
+
"data-risk": combinedRisk,
|
|
6481
|
+
"data-current-week": isCurrentWeek,
|
|
6482
|
+
onClick: handleClick,
|
|
6483
|
+
onKeyDown: handleKeyDown,
|
|
6484
|
+
role: "button",
|
|
6485
|
+
tabIndex: 0,
|
|
6486
|
+
className: cn(
|
|
6487
|
+
"flex flex-col h-[80px] justify-center gap-2",
|
|
6488
|
+
"cursor-pointer",
|
|
6489
|
+
// Edge-to-edge status fill (no inset card)
|
|
6490
|
+
statusClasses.border,
|
|
6491
|
+
statusClasses.bg,
|
|
6492
|
+
spacingClasses,
|
|
6493
|
+
// Hover lift effect
|
|
6494
|
+
"transition-all duration-200 ease-out",
|
|
6495
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
6496
|
+
className
|
|
6497
|
+
),
|
|
6498
|
+
...props,
|
|
6499
|
+
children: [
|
|
6500
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6501
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: cn("h-3.5 w-3.5 shrink-0", productionColors.icon) }),
|
|
6502
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6503
|
+
"div",
|
|
6504
|
+
{
|
|
6505
|
+
className: cn("h-full rounded-full transition-all", productionColors.progress),
|
|
6506
|
+
style: { width: `${productionProgress}%` }
|
|
6507
|
+
}
|
|
6508
|
+
) })
|
|
6509
|
+
] }),
|
|
6510
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6511
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn("h-3.5 w-3.5 shrink-0", deliveryColors.icon) }),
|
|
6512
|
+
deliveryCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-[10px] font-medium", deliveryColors.text), children: [
|
|
6513
|
+
deliveryCount,
|
|
6514
|
+
"x delivery"
|
|
6515
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2014" })
|
|
6516
|
+
] }),
|
|
6517
|
+
deliveryCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6518
|
+
data.deliveries?.slice(0, 5).map((delivery, index) => {
|
|
6519
|
+
const deliveryProgress = delivery.progress ?? (delivery.status === "on-time" ? 100 : delivery.status === "delayed" ? 50 : 25);
|
|
6520
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6521
|
+
"div",
|
|
6522
|
+
{
|
|
6523
|
+
className: "flex-1 max-w-[24px]",
|
|
6524
|
+
title: delivery.label || `Delivery ${index + 1}`,
|
|
6525
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6526
|
+
"div",
|
|
6527
|
+
{
|
|
6528
|
+
className: cn("h-full rounded-full transition-all", getDeliveryStatusColor(delivery.status)),
|
|
6529
|
+
style: { width: `${deliveryProgress}%` }
|
|
6530
|
+
}
|
|
6531
|
+
) })
|
|
6532
|
+
},
|
|
6533
|
+
delivery.id || index
|
|
6534
|
+
);
|
|
6535
|
+
}),
|
|
6536
|
+
deliveryCount > 5 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[8px] text-muted-foreground", children: [
|
|
6537
|
+
"+",
|
|
6538
|
+
deliveryCount - 5
|
|
6539
|
+
] })
|
|
6540
|
+
] })
|
|
6541
|
+
]
|
|
6542
|
+
}
|
|
6543
|
+
);
|
|
6544
|
+
}
|
|
6545
|
+
function CommentButton({
|
|
6546
|
+
className,
|
|
6547
|
+
commentCount = 0,
|
|
6548
|
+
size = "default",
|
|
6549
|
+
...props
|
|
6550
|
+
}) {
|
|
6551
|
+
const hasComments = commentCount > 0;
|
|
6552
|
+
const sizeClasses = size === "sm" ? "h-6 w-6" : "h-7 w-7";
|
|
6553
|
+
const iconSize = size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4";
|
|
6554
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6555
|
+
Button,
|
|
6556
|
+
{
|
|
6557
|
+
variant: "outline",
|
|
6558
|
+
size: "icon",
|
|
6559
|
+
className: cn(
|
|
6560
|
+
sizeClasses,
|
|
6561
|
+
"rounded-full shrink-0 relative",
|
|
6562
|
+
"border-border bg-background hover:bg-muted",
|
|
6563
|
+
"shadow-[var(--j3m-shadow-sm)]",
|
|
6564
|
+
hasComments && "border-primary/50",
|
|
6565
|
+
className
|
|
6566
|
+
),
|
|
6567
|
+
...props,
|
|
6568
|
+
children: [
|
|
6569
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: cn(iconSize, hasComments && "text-primary") }),
|
|
6570
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6571
|
+
"span",
|
|
6572
|
+
{
|
|
6573
|
+
className: cn(
|
|
6574
|
+
"absolute -top-0.5 -right-0.5",
|
|
6575
|
+
"h-2.5 w-2.5 rounded-full",
|
|
6576
|
+
"bg-primary",
|
|
6577
|
+
"border border-background"
|
|
6578
|
+
// Subtle outline for contrast
|
|
6579
|
+
),
|
|
6580
|
+
"aria-hidden": "true"
|
|
6581
|
+
}
|
|
6582
|
+
),
|
|
6583
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: hasComments ? `${commentCount} comment${commentCount > 1 ? "s" : ""}` : "Add comment" })
|
|
6584
|
+
]
|
|
6585
|
+
}
|
|
6586
|
+
);
|
|
6587
|
+
}
|
|
6588
|
+
|
|
6589
|
+
// src/blocks/planning-table/types.ts
|
|
6590
|
+
function getCommentLocationLabel(location) {
|
|
6591
|
+
if (location.type === "production") {
|
|
6592
|
+
return location.supplierName ? `Production - ${location.supplierName}` : "Production";
|
|
6593
|
+
}
|
|
6594
|
+
if (location.type === "delivery") {
|
|
6595
|
+
return location.deliveryLabel || `Delivery ${location.deliveryId || ""}`;
|
|
6596
|
+
}
|
|
6597
|
+
return "Unknown";
|
|
6598
|
+
}
|
|
6599
|
+
function getElementShipmentStatus(element, currentDeliveryId) {
|
|
6600
|
+
if (element.shipmentStatus) {
|
|
6601
|
+
return element.shipmentStatus;
|
|
6602
|
+
}
|
|
6603
|
+
if (element.isProduced) {
|
|
6604
|
+
if (element.actualDeliveryId && element.actualDeliveryId !== currentDeliveryId) {
|
|
6605
|
+
return "moved";
|
|
6606
|
+
}
|
|
6607
|
+
return "sent";
|
|
6608
|
+
}
|
|
6609
|
+
if (element.originalDeliveryId && element.originalDeliveryId !== currentDeliveryId) {
|
|
6610
|
+
return "addon";
|
|
6611
|
+
}
|
|
6612
|
+
return "not-sent";
|
|
6613
|
+
}
|
|
6614
|
+
function getShipmentStatusLabel(status) {
|
|
6615
|
+
switch (status) {
|
|
6616
|
+
case "sent":
|
|
6617
|
+
return "Sent";
|
|
6618
|
+
case "not-sent":
|
|
6619
|
+
return "Missing";
|
|
6620
|
+
// Neutral tone, not "Not sent"
|
|
6621
|
+
case "moved":
|
|
6622
|
+
return "Moved to another delivery";
|
|
6623
|
+
case "addon":
|
|
6624
|
+
return "Add-on";
|
|
6625
|
+
case "planned":
|
|
6626
|
+
return "Planned";
|
|
6627
|
+
default:
|
|
6628
|
+
return status;
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
function getWeekKey(date) {
|
|
6632
|
+
const year = date.getFullYear();
|
|
6633
|
+
const weekNumber = getISOWeek(date);
|
|
6634
|
+
return `${year}-W${weekNumber.toString().padStart(2, "0")}`;
|
|
6635
|
+
}
|
|
6636
|
+
function getISOWeek(date) {
|
|
6637
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
6638
|
+
const dayNum = d.getUTCDay() || 7;
|
|
6639
|
+
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
6640
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
6641
|
+
return Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
6642
|
+
}
|
|
6643
|
+
function generateWeeks(startDate, count) {
|
|
6644
|
+
const weeks = [];
|
|
6645
|
+
const current = new Date(startDate);
|
|
6646
|
+
const today = /* @__PURE__ */ new Date();
|
|
6647
|
+
const currentWeekKey = getWeekKey(today);
|
|
6648
|
+
const dayOfWeek = current.getDay();
|
|
6649
|
+
const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
|
6650
|
+
current.setDate(current.getDate() + daysToMonday);
|
|
6651
|
+
for (let i = 0; i < count; i++) {
|
|
6652
|
+
const weekStart = new Date(current);
|
|
6653
|
+
const weekEnd = new Date(current);
|
|
6654
|
+
weekEnd.setDate(weekEnd.getDate() + 6);
|
|
6655
|
+
const weekNumber = getISOWeek(weekStart);
|
|
6656
|
+
const year = weekStart.getFullYear();
|
|
6657
|
+
const weekKey = `${year}-W${weekNumber.toString().padStart(2, "0")}`;
|
|
6658
|
+
weeks.push({
|
|
6659
|
+
weekNumber,
|
|
6660
|
+
year,
|
|
6661
|
+
startDate: weekStart,
|
|
6662
|
+
endDate: weekEnd,
|
|
6663
|
+
label: `W${weekNumber.toString().padStart(2, "0")}`,
|
|
6664
|
+
dateRange: formatDateRange(weekStart, weekEnd),
|
|
6665
|
+
isCurrentWeek: weekKey === currentWeekKey
|
|
6666
|
+
});
|
|
6667
|
+
current.setDate(current.getDate() + 7);
|
|
6668
|
+
}
|
|
6669
|
+
return weeks;
|
|
6670
|
+
}
|
|
6671
|
+
function formatDateRange(start, end) {
|
|
6672
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
6673
|
+
const startMonth = months[start.getMonth()];
|
|
6674
|
+
const endMonth = months[end.getMonth()];
|
|
6675
|
+
if (startMonth === endMonth) {
|
|
6676
|
+
return `${startMonth} ${start.getDate()} - ${end.getDate()}`;
|
|
6677
|
+
}
|
|
6678
|
+
return `${startMonth} ${start.getDate()} - ${endMonth} ${end.getDate()}`;
|
|
6679
|
+
}
|
|
6680
|
+
function formatProductionUnit(unit) {
|
|
6681
|
+
const unitLabels = {
|
|
6682
|
+
quantity: "pcs",
|
|
6683
|
+
kvm: "m\xB2",
|
|
6684
|
+
ton: "ton",
|
|
6685
|
+
kg: "kg",
|
|
6686
|
+
m: "m",
|
|
6687
|
+
pcs: "pcs"
|
|
6688
|
+
};
|
|
6689
|
+
return unitLabels[unit] || unit;
|
|
6690
|
+
}
|
|
6691
|
+
function LocationIcon({ type }) {
|
|
6692
|
+
if (type === "production") {
|
|
6693
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-3 w-3" });
|
|
6694
|
+
}
|
|
6695
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3 w-3" });
|
|
6696
|
+
}
|
|
6697
|
+
function PlanningWeekCommentPopover({
|
|
6698
|
+
comments,
|
|
6699
|
+
weekLabel,
|
|
6700
|
+
weekKey,
|
|
6701
|
+
locationOptions,
|
|
6702
|
+
onAddComment,
|
|
6703
|
+
onCommentClick,
|
|
6704
|
+
open,
|
|
6705
|
+
onOpenChange
|
|
6706
|
+
}) {
|
|
6707
|
+
const [newCommentText, setNewCommentText] = React22__namespace.useState("");
|
|
6708
|
+
const [selectedLocationId, setSelectedLocationId] = React22__namespace.useState("");
|
|
6709
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22__namespace.useState(true);
|
|
6710
|
+
const [showAddForm, setShowAddForm] = React22__namespace.useState(false);
|
|
6711
|
+
const selectedLocation = React22__namespace.useMemo(() => {
|
|
6712
|
+
return locationOptions.find((opt) => opt.id === selectedLocationId);
|
|
6713
|
+
}, [locationOptions, selectedLocationId]);
|
|
6714
|
+
const handleSubmit = () => {
|
|
6715
|
+
if (newCommentText.trim() && selectedLocation && onAddComment) {
|
|
6716
|
+
const location = {
|
|
6717
|
+
type: selectedLocation.type,
|
|
6718
|
+
weekKey,
|
|
6719
|
+
supplierId: selectedLocation.supplierId,
|
|
6720
|
+
supplierName: selectedLocation.supplierName,
|
|
6721
|
+
deliveryId: selectedLocation.deliveryId,
|
|
6722
|
+
deliveryLabel: selectedLocation.deliveryLabel
|
|
6723
|
+
};
|
|
6724
|
+
onAddComment(newCommentText.trim(), location);
|
|
6725
|
+
setNewCommentText("");
|
|
6726
|
+
setSelectedLocationId("");
|
|
6727
|
+
setShowAddForm(false);
|
|
6728
|
+
setViewCommentsOpen(true);
|
|
6729
|
+
}
|
|
6730
|
+
};
|
|
6731
|
+
const handleKeyDown = (e) => {
|
|
6732
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
6733
|
+
e.preventDefault();
|
|
6734
|
+
handleSubmit();
|
|
6735
|
+
}
|
|
6736
|
+
if (e.key === "Escape") {
|
|
6737
|
+
setShowAddForm(false);
|
|
6738
|
+
setSelectedLocationId("");
|
|
6739
|
+
setNewCommentText("");
|
|
6740
|
+
}
|
|
6741
|
+
};
|
|
6742
|
+
const handleCommentClick = (comment) => {
|
|
6743
|
+
if (comment.location && onCommentClick) {
|
|
6744
|
+
onCommentClick(comment);
|
|
6745
|
+
}
|
|
6746
|
+
};
|
|
6747
|
+
const formatDate2 = (date) => {
|
|
6748
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
6749
|
+
month: "short",
|
|
6750
|
+
day: "numeric",
|
|
6751
|
+
hour: "numeric",
|
|
6752
|
+
minute: "2-digit"
|
|
6753
|
+
}).format(date);
|
|
6754
|
+
};
|
|
6755
|
+
const prevOpenRef = React22__namespace.useRef(open);
|
|
6756
|
+
React22__namespace.useEffect(() => {
|
|
6757
|
+
const wasOpen = prevOpenRef.current;
|
|
6758
|
+
prevOpenRef.current = open;
|
|
6759
|
+
if (wasOpen && !open) {
|
|
6760
|
+
setShowAddForm(false);
|
|
6761
|
+
setNewCommentText("");
|
|
6762
|
+
setSelectedLocationId("");
|
|
6763
|
+
}
|
|
6764
|
+
}, [open]);
|
|
6765
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange, children: [
|
|
6766
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
6767
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6768
|
+
PopoverContent,
|
|
6769
|
+
{
|
|
6770
|
+
className: "w-80 p-0 z-[100]",
|
|
6771
|
+
align: "end",
|
|
6772
|
+
sideOffset: 8,
|
|
6773
|
+
collisionPadding: 16,
|
|
6774
|
+
children: [
|
|
6775
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
6776
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
6777
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: weekLabel })
|
|
6778
|
+
] }),
|
|
6779
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
6780
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
6781
|
+
/* @__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: [
|
|
6782
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium", children: [
|
|
6783
|
+
"Comments ",
|
|
6784
|
+
comments.length > 0 && `(${comments.length})`
|
|
6785
|
+
] }),
|
|
6786
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
|
|
6787
|
+
"h-4 w-4 transition-transform duration-200",
|
|
6788
|
+
viewCommentsOpen && "rotate-180"
|
|
6789
|
+
) })
|
|
6790
|
+
] }) }),
|
|
6791
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => {
|
|
6792
|
+
const hasLocation = !!comment.location;
|
|
6793
|
+
const locationLabel = comment.location ? getCommentLocationLabel(comment.location) : null;
|
|
6794
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6795
|
+
"div",
|
|
6796
|
+
{
|
|
6797
|
+
className: cn(
|
|
6798
|
+
"rounded-lg bg-muted/50 p-3 space-y-2",
|
|
6799
|
+
hasLocation && "cursor-pointer hover:bg-muted/70 transition-colors"
|
|
6800
|
+
),
|
|
6801
|
+
onClick: () => handleCommentClick(comment),
|
|
6802
|
+
role: hasLocation ? "button" : void 0,
|
|
6803
|
+
tabIndex: hasLocation ? 0 : void 0,
|
|
6804
|
+
onKeyDown: hasLocation ? (e) => {
|
|
6805
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6806
|
+
e.preventDefault();
|
|
6807
|
+
handleCommentClick(comment);
|
|
6808
|
+
}
|
|
6809
|
+
} : void 0,
|
|
6810
|
+
children: [
|
|
6811
|
+
locationLabel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6812
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6813
|
+
Badge,
|
|
6814
|
+
{
|
|
6815
|
+
variant: "outline",
|
|
6816
|
+
className: "text-[10px] px-2 py-0 h-5 font-medium bg-background gap-1",
|
|
6817
|
+
children: [
|
|
6818
|
+
/* @__PURE__ */ jsxRuntime.jsx(LocationIcon, { type: comment.location.type }),
|
|
6819
|
+
locationLabel
|
|
6820
|
+
]
|
|
6821
|
+
}
|
|
6822
|
+
),
|
|
6823
|
+
hasLocation && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-3 w-3 text-muted-foreground" })
|
|
6824
|
+
] }),
|
|
6825
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6826
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
6827
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
6828
|
+
] }),
|
|
6829
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
6830
|
+
]
|
|
6831
|
+
},
|
|
6832
|
+
comment.id
|
|
6833
|
+
);
|
|
6834
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
6835
|
+
] }),
|
|
6836
|
+
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
6837
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6838
|
+
Button,
|
|
6839
|
+
{
|
|
6840
|
+
variant: "outline",
|
|
6841
|
+
size: "sm",
|
|
6842
|
+
className: "w-full justify-center gap-2 h-8",
|
|
6843
|
+
onClick: () => setShowAddForm(true),
|
|
6844
|
+
disabled: locationOptions.length === 0,
|
|
6845
|
+
children: [
|
|
6846
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
6847
|
+
locationOptions.length === 0 ? "No suppliers available" : "Add comment"
|
|
6848
|
+
]
|
|
6849
|
+
}
|
|
6850
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
6851
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
6852
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
6853
|
+
), children: [
|
|
6854
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
6855
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label2, { htmlFor: "supplier-prefix-select", className: "text-xs font-medium", children: [
|
|
6856
|
+
"Supplier / Prefix ",
|
|
6857
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive", children: "*" })
|
|
6858
|
+
] }),
|
|
6859
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedLocationId, onValueChange: setSelectedLocationId, children: [
|
|
6860
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: "supplier-prefix-select", size: "sm", className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select supplier / prefix..." }) }),
|
|
6861
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: locationOptions.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.id, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6862
|
+
/* @__PURE__ */ jsxRuntime.jsx(LocationIcon, { type: option.type }),
|
|
6863
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label })
|
|
6864
|
+
] }) }, option.id)) })
|
|
6865
|
+
] })
|
|
6866
|
+
] }),
|
|
6867
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
6868
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "comment-text", className: "text-xs font-medium", children: "Comment" }),
|
|
6869
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6870
|
+
Textarea,
|
|
6871
|
+
{
|
|
6872
|
+
id: "comment-text",
|
|
6873
|
+
placeholder: "Type your comment...",
|
|
6874
|
+
value: newCommentText,
|
|
6875
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
6876
|
+
onKeyDown: handleKeyDown,
|
|
6877
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
6878
|
+
autoFocus: true
|
|
6879
|
+
}
|
|
6880
|
+
)
|
|
6881
|
+
] }),
|
|
6882
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6883
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
6884
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6885
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6886
|
+
Button,
|
|
6887
|
+
{
|
|
6888
|
+
variant: "ghost",
|
|
6889
|
+
size: "sm",
|
|
6890
|
+
className: "h-7",
|
|
6891
|
+
onClick: () => {
|
|
6892
|
+
setShowAddForm(false);
|
|
6893
|
+
setNewCommentText("");
|
|
6894
|
+
setSelectedLocationId("");
|
|
6895
|
+
},
|
|
6896
|
+
children: "Cancel"
|
|
6897
|
+
}
|
|
6898
|
+
),
|
|
6899
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6900
|
+
Button,
|
|
6901
|
+
{
|
|
6902
|
+
size: "sm",
|
|
6903
|
+
className: "h-7 gap-1",
|
|
6904
|
+
onClick: handleSubmit,
|
|
6905
|
+
disabled: !newCommentText.trim() || !selectedLocationId,
|
|
6906
|
+
children: [
|
|
6907
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
6908
|
+
"Save"
|
|
6909
|
+
]
|
|
6910
|
+
}
|
|
6911
|
+
)
|
|
6912
|
+
] })
|
|
6913
|
+
] })
|
|
6914
|
+
] })
|
|
6915
|
+
] })
|
|
6916
|
+
]
|
|
6917
|
+
}
|
|
6918
|
+
)
|
|
6919
|
+
] });
|
|
6920
|
+
}
|
|
6921
|
+
function generateLocationOptions(suppliers, weekKey) {
|
|
6922
|
+
const options = [];
|
|
6923
|
+
for (const supplier of suppliers) {
|
|
6924
|
+
const weekData = supplier.weeks[weekKey];
|
|
6925
|
+
options.push({
|
|
6926
|
+
id: `${supplier.id}-production`,
|
|
6927
|
+
label: `${supplier.name} - Production`,
|
|
6928
|
+
type: "production",
|
|
6929
|
+
supplierId: supplier.id,
|
|
6930
|
+
supplierName: supplier.name
|
|
6931
|
+
});
|
|
6932
|
+
if (weekData?.deliveries) {
|
|
6933
|
+
for (const delivery of weekData.deliveries) {
|
|
6934
|
+
options.push({
|
|
6935
|
+
id: `${supplier.id}-delivery-${delivery.id}`,
|
|
6936
|
+
label: `${supplier.name} - ${delivery.label || `Delivery ${delivery.id}`}`,
|
|
6937
|
+
type: "delivery",
|
|
6938
|
+
supplierId: supplier.id,
|
|
6939
|
+
supplierName: supplier.name,
|
|
6940
|
+
deliveryId: delivery.id,
|
|
6941
|
+
deliveryLabel: delivery.label || `Delivery ${delivery.id}`
|
|
6942
|
+
});
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6945
|
+
}
|
|
6946
|
+
return options;
|
|
6947
|
+
}
|
|
6948
|
+
function WeekHeader({
|
|
6949
|
+
className,
|
|
6950
|
+
week,
|
|
6951
|
+
weekKey,
|
|
6952
|
+
comments = [],
|
|
6953
|
+
showCommentButton = true,
|
|
6954
|
+
locationOptions = [],
|
|
6955
|
+
onAddComment,
|
|
6956
|
+
onCommentClick,
|
|
6957
|
+
...props
|
|
6958
|
+
}) {
|
|
6959
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6960
|
+
"div",
|
|
6961
|
+
{
|
|
6962
|
+
"data-slot": "week-header",
|
|
6963
|
+
"data-current-week": week.isCurrentWeek,
|
|
6964
|
+
className: cn(
|
|
6965
|
+
"flex items-center justify-between gap-2 min-w-[140px] text-left",
|
|
6966
|
+
className
|
|
6967
|
+
),
|
|
6968
|
+
...props,
|
|
6969
|
+
children: [
|
|
6970
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
6971
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6972
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
6973
|
+
"text-sm font-semibold tracking-tight",
|
|
6974
|
+
week.isCurrentWeek ? "text-primary" : "text-foreground"
|
|
6975
|
+
), children: week.label }),
|
|
6976
|
+
week.isCurrentWeek && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
6977
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75" }),
|
|
6978
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary" })
|
|
6979
|
+
] })
|
|
6980
|
+
] }),
|
|
6981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-normal text-muted-foreground/60 whitespace-nowrap", children: week.dateRange })
|
|
6982
|
+
] }),
|
|
6983
|
+
showCommentButton && weekKey && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6984
|
+
PlanningWeekCommentPopover,
|
|
6985
|
+
{
|
|
6986
|
+
comments,
|
|
6987
|
+
weekLabel: week.label,
|
|
6988
|
+
weekKey,
|
|
6989
|
+
locationOptions,
|
|
6990
|
+
onAddComment,
|
|
6991
|
+
onCommentClick
|
|
6992
|
+
}
|
|
6993
|
+
)
|
|
6994
|
+
]
|
|
6995
|
+
}
|
|
6996
|
+
);
|
|
6997
|
+
}
|
|
6998
|
+
function SupplierColumnHeader({
|
|
6999
|
+
column
|
|
7000
|
+
}) {
|
|
7001
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7002
|
+
Button,
|
|
7003
|
+
{
|
|
7004
|
+
variant: "ghost",
|
|
7005
|
+
size: "sm",
|
|
7006
|
+
className: "-ml-3 h-8 data-[state=open]:bg-accent",
|
|
7007
|
+
onClick: () => column.toggleSorting(column.getIsSorted() === "asc"),
|
|
7008
|
+
children: [
|
|
7009
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Supplier / Scope" }),
|
|
7010
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpDown, { className: "ml-2 h-4 w-4" })
|
|
7011
|
+
]
|
|
7012
|
+
}
|
|
7013
|
+
);
|
|
7014
|
+
}
|
|
7015
|
+
function getSupplierColumn() {
|
|
7016
|
+
return {
|
|
7017
|
+
id: "supplier",
|
|
7018
|
+
accessorKey: "name",
|
|
7019
|
+
header: ({ column }) => /* @__PURE__ */ jsxRuntime.jsx(SupplierColumnHeader, { column }),
|
|
7020
|
+
cell: ({ row }) => /* @__PURE__ */ jsxRuntime.jsx(SupplierCell, { supplier: row.original }),
|
|
7021
|
+
enableSorting: true,
|
|
7022
|
+
enableHiding: false
|
|
7023
|
+
};
|
|
7024
|
+
}
|
|
7025
|
+
function WeekHeaderWithComments({
|
|
7026
|
+
week,
|
|
7027
|
+
weekKey,
|
|
7028
|
+
config,
|
|
7029
|
+
suppliers
|
|
7030
|
+
}) {
|
|
7031
|
+
const weekComments = config?.weekComments?.[weekKey] ?? [];
|
|
7032
|
+
let filteredSuppliers = suppliers;
|
|
7033
|
+
if (config?.userRole === "supplier" && config?.currentSupplierId) {
|
|
7034
|
+
filteredSuppliers = suppliers.filter((s) => s.id === config.currentSupplierId);
|
|
7035
|
+
}
|
|
7036
|
+
const locationOptions = generateLocationOptions(filteredSuppliers, weekKey);
|
|
7037
|
+
const handleAddComment = config?.onAddWeekComment ? (text, location) => {
|
|
7038
|
+
config.onAddWeekComment?.(weekKey, text, location);
|
|
7039
|
+
} : void 0;
|
|
7040
|
+
const handleCommentClick = config?.onCommentClick;
|
|
7041
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7042
|
+
WeekHeader,
|
|
7043
|
+
{
|
|
7044
|
+
week,
|
|
7045
|
+
weekKey,
|
|
7046
|
+
comments: weekComments,
|
|
7047
|
+
showCommentButton: true,
|
|
7048
|
+
locationOptions,
|
|
7049
|
+
onAddComment: handleAddComment,
|
|
7050
|
+
onCommentClick: handleCommentClick
|
|
7051
|
+
}
|
|
7052
|
+
);
|
|
7053
|
+
}
|
|
7054
|
+
function generateWeekColumns(weeks, config, suppliers) {
|
|
7055
|
+
return weeks.map((week) => {
|
|
7056
|
+
const weekKey = getWeekKey(week.startDate);
|
|
7057
|
+
return {
|
|
7058
|
+
id: weekKey,
|
|
7059
|
+
accessorFn: (supplier) => supplier.weeks[weekKey],
|
|
7060
|
+
header: () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7061
|
+
WeekHeaderWithComments,
|
|
7062
|
+
{
|
|
7063
|
+
week,
|
|
7064
|
+
weekKey,
|
|
7065
|
+
config,
|
|
7066
|
+
suppliers: suppliers ?? []
|
|
7067
|
+
}
|
|
7068
|
+
),
|
|
7069
|
+
cell: ({ row }) => {
|
|
7070
|
+
const supplier = row.original;
|
|
7071
|
+
const data = supplier.weeks[weekKey] || { type: "empty" };
|
|
7072
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7073
|
+
WeekCell,
|
|
7074
|
+
{
|
|
7075
|
+
data,
|
|
7076
|
+
week,
|
|
7077
|
+
supplier,
|
|
7078
|
+
isCurrentWeek: week.isCurrentWeek,
|
|
7079
|
+
onCellClick: config?.onCellClick ? () => config.onCellClick?.(supplier, week, data) : void 0
|
|
7080
|
+
}
|
|
7081
|
+
);
|
|
7082
|
+
},
|
|
7083
|
+
enableSorting: false,
|
|
7084
|
+
enableHiding: true
|
|
7085
|
+
};
|
|
7086
|
+
});
|
|
7087
|
+
}
|
|
7088
|
+
function generateColumns(weeks, config, suppliers) {
|
|
7089
|
+
return [
|
|
7090
|
+
getSupplierColumn(),
|
|
7091
|
+
...generateWeekColumns(weeks, config, suppliers)
|
|
7092
|
+
];
|
|
7093
|
+
}
|
|
7094
|
+
function PlanningTable({
|
|
7095
|
+
className,
|
|
7096
|
+
suppliers,
|
|
7097
|
+
config = {}
|
|
7098
|
+
}) {
|
|
7099
|
+
const {
|
|
7100
|
+
weekCount = 12,
|
|
7101
|
+
startDate = /* @__PURE__ */ new Date(),
|
|
7102
|
+
highlightCurrentWeek = true,
|
|
7103
|
+
showToolbar = true,
|
|
7104
|
+
showPagination = true,
|
|
7105
|
+
pageSizeOptions = [10, 20, 30, 50],
|
|
7106
|
+
defaultPageSize = 10,
|
|
7107
|
+
stickySupplierColumn = true,
|
|
7108
|
+
maxHeight = "600px"
|
|
7109
|
+
} = config;
|
|
7110
|
+
const weeks = React22__namespace.useMemo(
|
|
7111
|
+
() => generateWeeks(startDate, weekCount),
|
|
7112
|
+
[startDate, weekCount]
|
|
7113
|
+
);
|
|
7114
|
+
const currentWeekKey = React22__namespace.useMemo(() => {
|
|
7115
|
+
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
7116
|
+
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
7117
|
+
}, [weeks]);
|
|
7118
|
+
const columns = React22__namespace.useMemo(
|
|
7119
|
+
() => generateColumns(weeks, config, suppliers),
|
|
7120
|
+
[weeks, config, suppliers]
|
|
7121
|
+
);
|
|
7122
|
+
const [sorting, setSorting] = React22__namespace.useState([]);
|
|
7123
|
+
const [columnFilters, setColumnFilters] = React22__namespace.useState([]);
|
|
7124
|
+
const [columnVisibility, setColumnVisibility] = React22__namespace.useState({});
|
|
7125
|
+
const [rowSelection, setRowSelection] = React22__namespace.useState({});
|
|
7126
|
+
const table = reactTable.useReactTable({
|
|
7127
|
+
data: suppliers,
|
|
7128
|
+
columns,
|
|
7129
|
+
getCoreRowModel: reactTable.getCoreRowModel(),
|
|
7130
|
+
getSortedRowModel: reactTable.getSortedRowModel(),
|
|
7131
|
+
getFilteredRowModel: reactTable.getFilteredRowModel(),
|
|
7132
|
+
getPaginationRowModel: reactTable.getPaginationRowModel(),
|
|
7133
|
+
onSortingChange: setSorting,
|
|
7134
|
+
onColumnFiltersChange: setColumnFilters,
|
|
7135
|
+
onColumnVisibilityChange: setColumnVisibility,
|
|
7136
|
+
onRowSelectionChange: setRowSelection,
|
|
7137
|
+
state: {
|
|
7138
|
+
sorting,
|
|
7139
|
+
columnFilters,
|
|
7140
|
+
columnVisibility,
|
|
7141
|
+
rowSelection
|
|
7142
|
+
},
|
|
7143
|
+
initialState: {
|
|
7144
|
+
pagination: {
|
|
7145
|
+
pageSize: defaultPageSize
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
7148
|
+
});
|
|
7149
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7150
|
+
"div",
|
|
7151
|
+
{
|
|
7152
|
+
"data-slot": "planning-table",
|
|
7153
|
+
className: cn("flex flex-col gap-4", className),
|
|
7154
|
+
children: [
|
|
7155
|
+
showToolbar && /* @__PURE__ */ jsxRuntime.jsx(PlanningTableToolbar, { table }),
|
|
7156
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border bg-background shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7157
|
+
ScrollArea,
|
|
7158
|
+
{
|
|
7159
|
+
className: "w-full",
|
|
7160
|
+
style: { maxHeight },
|
|
7161
|
+
children: [
|
|
7162
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
|
|
7163
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "sticky top-0 z-20", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7164
|
+
"tr",
|
|
7165
|
+
{
|
|
7166
|
+
children: headerGroup.headers.map((header, index) => {
|
|
7167
|
+
const isCurrentWeekColumn = header.id === currentWeekKey;
|
|
7168
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7169
|
+
"th",
|
|
7170
|
+
{
|
|
7171
|
+
className: cn(
|
|
7172
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
7173
|
+
"border-r border-b border-border last:border-r-0 bg-sidebar",
|
|
7174
|
+
// First column: sticky with right-edge shadow (Quantum token)
|
|
7175
|
+
index === 0 && stickySupplierColumn && [
|
|
7176
|
+
"sticky left-0 z-30 min-w-[200px]",
|
|
7177
|
+
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7178
|
+
],
|
|
7179
|
+
index > 0 && "min-w-[140px]",
|
|
7180
|
+
// Current week: only highlight text/dot, not full background
|
|
7181
|
+
isCurrentWeekColumn && highlightCurrentWeek && "text-primary"
|
|
7182
|
+
),
|
|
7183
|
+
children: header.isPlaceholder ? null : reactTable.flexRender(
|
|
7184
|
+
header.column.columnDef.header,
|
|
7185
|
+
header.getContext()
|
|
7186
|
+
)
|
|
7187
|
+
},
|
|
7188
|
+
header.id
|
|
7189
|
+
);
|
|
7190
|
+
})
|
|
7191
|
+
},
|
|
7192
|
+
headerGroup.id
|
|
7193
|
+
)) }),
|
|
7194
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-background", children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7195
|
+
"tr",
|
|
7196
|
+
{
|
|
7197
|
+
"data-state": row.getIsSelected() && "selected",
|
|
7198
|
+
className: "border-b border-border last:border-b-0",
|
|
7199
|
+
children: row.getVisibleCells().map((cell, index) => {
|
|
7200
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7201
|
+
"td",
|
|
7202
|
+
{
|
|
7203
|
+
className: cn(
|
|
7204
|
+
"p-0 align-top border-r border-border last:border-r-0 bg-background",
|
|
7205
|
+
// First column: sticky WHITE with right-edge shadow (Quantum token)
|
|
7206
|
+
index === 0 && stickySupplierColumn && [
|
|
7207
|
+
"sticky left-0 z-10 min-w-[200px]",
|
|
7208
|
+
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7209
|
+
],
|
|
7210
|
+
index > 0 && "min-w-[140px]"
|
|
7211
|
+
),
|
|
7212
|
+
children: reactTable.flexRender(
|
|
7213
|
+
cell.column.columnDef.cell,
|
|
7214
|
+
cell.getContext()
|
|
7215
|
+
)
|
|
7216
|
+
},
|
|
7217
|
+
cell.id
|
|
7218
|
+
);
|
|
7219
|
+
})
|
|
7220
|
+
},
|
|
7221
|
+
row.id
|
|
7222
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7223
|
+
"td",
|
|
7224
|
+
{
|
|
7225
|
+
colSpan: columns.length,
|
|
7226
|
+
className: "h-24 text-center text-muted-foreground bg-background",
|
|
7227
|
+
children: "No suppliers found."
|
|
7228
|
+
}
|
|
7229
|
+
) }) })
|
|
7230
|
+
] }),
|
|
7231
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, { orientation: "horizontal" }),
|
|
7232
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, { orientation: "vertical" })
|
|
7233
|
+
]
|
|
7234
|
+
}
|
|
7235
|
+
) }),
|
|
7236
|
+
showPagination && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7237
|
+
DataTablePagination,
|
|
7238
|
+
{
|
|
7239
|
+
table,
|
|
7240
|
+
showRowSelection: false,
|
|
7241
|
+
pageSizeOptions
|
|
7242
|
+
}
|
|
7243
|
+
)
|
|
7244
|
+
]
|
|
7245
|
+
}
|
|
7246
|
+
);
|
|
7247
|
+
}
|
|
7248
|
+
function getStatusBadgeVariant(status) {
|
|
7249
|
+
switch (status) {
|
|
7250
|
+
case "on-time":
|
|
7251
|
+
return "outline";
|
|
7252
|
+
case "delayed":
|
|
7253
|
+
return "secondary";
|
|
7254
|
+
case "critical":
|
|
7255
|
+
return "destructive";
|
|
7256
|
+
default:
|
|
7257
|
+
return "outline";
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
function getStatusBadgeClasses(status) {
|
|
7261
|
+
switch (status) {
|
|
7262
|
+
case "on-time":
|
|
7263
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7264
|
+
case "delayed":
|
|
7265
|
+
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
7266
|
+
case "critical":
|
|
7267
|
+
return "";
|
|
7268
|
+
default:
|
|
7269
|
+
return "";
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
function getStatusLabel(status) {
|
|
7273
|
+
switch (status) {
|
|
7274
|
+
case "on-time":
|
|
7275
|
+
return "On Track";
|
|
7276
|
+
case "delayed":
|
|
7277
|
+
return "At Risk";
|
|
7278
|
+
case "critical":
|
|
7279
|
+
return "Critical";
|
|
7280
|
+
case "pending":
|
|
7281
|
+
return "Pending";
|
|
7282
|
+
default:
|
|
7283
|
+
return status;
|
|
7284
|
+
}
|
|
7285
|
+
}
|
|
7286
|
+
function getProgressVariant(status) {
|
|
7287
|
+
switch (status) {
|
|
7288
|
+
case "on-time":
|
|
7289
|
+
return "success";
|
|
7290
|
+
case "delayed":
|
|
7291
|
+
return "warning";
|
|
7292
|
+
case "critical":
|
|
7293
|
+
return "destructive";
|
|
7294
|
+
default:
|
|
7295
|
+
return "default";
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
function getShipmentStatusBadgeClasses(status) {
|
|
7299
|
+
switch (status) {
|
|
7300
|
+
case "sent":
|
|
7301
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7302
|
+
case "not-sent":
|
|
7303
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
7304
|
+
case "moved":
|
|
7305
|
+
return "border-blue-500 text-blue-600 bg-blue-50 dark:bg-blue-950/50";
|
|
7306
|
+
case "addon":
|
|
7307
|
+
return "border-purple-500 text-purple-600 bg-purple-50 dark:bg-purple-950/50";
|
|
7308
|
+
case "planned":
|
|
7309
|
+
default:
|
|
7310
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
function getShipmentStatusRowBg(status) {
|
|
7314
|
+
switch (status) {
|
|
7315
|
+
case "sent":
|
|
7316
|
+
return "bg-green-50/30 dark:bg-green-950/10";
|
|
7317
|
+
case "not-sent":
|
|
7318
|
+
return "bg-muted/30";
|
|
7319
|
+
case "moved":
|
|
7320
|
+
return "bg-blue-50/30 dark:bg-blue-950/10";
|
|
7321
|
+
case "addon":
|
|
7322
|
+
return "bg-purple-50/30 dark:bg-purple-950/10";
|
|
7323
|
+
default:
|
|
7324
|
+
return "";
|
|
7325
|
+
}
|
|
7326
|
+
}
|
|
7327
|
+
function DeliveryCommentPopover({
|
|
7328
|
+
comments = [],
|
|
7329
|
+
onAddComment,
|
|
7330
|
+
deliveryLabel
|
|
7331
|
+
}) {
|
|
7332
|
+
const [open, setOpen] = React22__namespace.useState(false);
|
|
7333
|
+
const [newCommentText, setNewCommentText] = React22__namespace.useState("");
|
|
7334
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22__namespace.useState(true);
|
|
7335
|
+
const [showAddForm, setShowAddForm] = React22__namespace.useState(false);
|
|
7336
|
+
const handleSubmit = () => {
|
|
7337
|
+
if (newCommentText.trim() && onAddComment) {
|
|
7338
|
+
onAddComment(newCommentText.trim());
|
|
7339
|
+
setNewCommentText("");
|
|
7340
|
+
setShowAddForm(false);
|
|
7341
|
+
setViewCommentsOpen(true);
|
|
7342
|
+
}
|
|
7343
|
+
};
|
|
7344
|
+
const handleKeyDown = (e) => {
|
|
7345
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
7346
|
+
e.preventDefault();
|
|
7347
|
+
handleSubmit();
|
|
7348
|
+
}
|
|
7349
|
+
if (e.key === "Escape") {
|
|
7350
|
+
setShowAddForm(false);
|
|
7351
|
+
setNewCommentText("");
|
|
7352
|
+
}
|
|
7353
|
+
};
|
|
7354
|
+
const formatDate2 = (date) => {
|
|
7355
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
7356
|
+
month: "short",
|
|
7357
|
+
day: "numeric",
|
|
7358
|
+
hour: "numeric",
|
|
7359
|
+
minute: "2-digit"
|
|
7360
|
+
}).format(date);
|
|
7361
|
+
};
|
|
7362
|
+
const prevOpenRef = React22__namespace.useRef(open);
|
|
7363
|
+
React22__namespace.useEffect(() => {
|
|
7364
|
+
const wasOpen = prevOpenRef.current;
|
|
7365
|
+
prevOpenRef.current = open;
|
|
7366
|
+
if (wasOpen && !open) {
|
|
7367
|
+
setShowAddForm(false);
|
|
7368
|
+
setNewCommentText("");
|
|
7369
|
+
}
|
|
7370
|
+
}, [open]);
|
|
7371
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
7372
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
7373
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7374
|
+
PopoverContent,
|
|
7375
|
+
{
|
|
7376
|
+
className: "w-80 p-0 z-[100]",
|
|
7377
|
+
align: "end",
|
|
7378
|
+
sideOffset: 8,
|
|
7379
|
+
collisionPadding: 16,
|
|
7380
|
+
children: [
|
|
7381
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
7382
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
7383
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: deliveryLabel })
|
|
7384
|
+
] }),
|
|
7385
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
7386
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
7387
|
+
/* @__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: [
|
|
7388
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium", children: [
|
|
7389
|
+
"Comments ",
|
|
7390
|
+
comments.length > 0 && `(${comments.length})`
|
|
7391
|
+
] }),
|
|
7392
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
|
|
7393
|
+
"h-4 w-4 transition-transform duration-200",
|
|
7394
|
+
viewCommentsOpen && "rotate-180"
|
|
7395
|
+
) })
|
|
7396
|
+
] }) }),
|
|
7397
|
+
/* @__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: [
|
|
7398
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7399
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7400
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
7401
|
+
] }),
|
|
7402
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7403
|
+
] }, comment.id)) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
7404
|
+
] }),
|
|
7405
|
+
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
7406
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7407
|
+
Button,
|
|
7408
|
+
{
|
|
7409
|
+
variant: "outline",
|
|
7410
|
+
size: "sm",
|
|
7411
|
+
className: "w-full justify-center gap-2 h-8",
|
|
7412
|
+
onClick: () => setShowAddForm(true),
|
|
7413
|
+
children: [
|
|
7414
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
7415
|
+
"Add comment"
|
|
7416
|
+
]
|
|
7417
|
+
}
|
|
7418
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
7419
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
7420
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
7421
|
+
), children: [
|
|
7422
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7423
|
+
Textarea,
|
|
7424
|
+
{
|
|
7425
|
+
placeholder: "Type your comment...",
|
|
7426
|
+
value: newCommentText,
|
|
7427
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
7428
|
+
onKeyDown: handleKeyDown,
|
|
7429
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
7430
|
+
autoFocus: true
|
|
7431
|
+
}
|
|
7432
|
+
),
|
|
7433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7434
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
7435
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7436
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7437
|
+
Button,
|
|
7438
|
+
{
|
|
7439
|
+
variant: "ghost",
|
|
7440
|
+
size: "sm",
|
|
7441
|
+
className: "h-7",
|
|
7442
|
+
onClick: () => {
|
|
7443
|
+
setShowAddForm(false);
|
|
7444
|
+
setNewCommentText("");
|
|
7445
|
+
},
|
|
7446
|
+
children: "Cancel"
|
|
7447
|
+
}
|
|
7448
|
+
),
|
|
7449
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7450
|
+
Button,
|
|
7451
|
+
{
|
|
7452
|
+
size: "sm",
|
|
7453
|
+
className: "h-7 gap-1",
|
|
7454
|
+
onClick: handleSubmit,
|
|
7455
|
+
disabled: !newCommentText.trim(),
|
|
7456
|
+
children: [
|
|
7457
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
7458
|
+
"Save"
|
|
7459
|
+
]
|
|
7460
|
+
}
|
|
7461
|
+
)
|
|
7462
|
+
] })
|
|
7463
|
+
] })
|
|
7464
|
+
] })
|
|
7465
|
+
] })
|
|
7466
|
+
]
|
|
7467
|
+
}
|
|
7468
|
+
)
|
|
7469
|
+
] });
|
|
7470
|
+
}
|
|
7471
|
+
function ProductionCommentSection({
|
|
7472
|
+
comments = [],
|
|
7473
|
+
onAddComment
|
|
7474
|
+
}) {
|
|
7475
|
+
const [showAddForm, setShowAddForm] = React22__namespace.useState(false);
|
|
7476
|
+
const [newComment, setNewComment] = React22__namespace.useState("");
|
|
7477
|
+
const handleSubmit = () => {
|
|
7478
|
+
if (newComment.trim() && onAddComment) {
|
|
7479
|
+
onAddComment(newComment.trim());
|
|
7480
|
+
setNewComment("");
|
|
7481
|
+
setShowAddForm(false);
|
|
7482
|
+
}
|
|
7483
|
+
};
|
|
7484
|
+
const handleKeyDown = (e) => {
|
|
7485
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
7486
|
+
e.preventDefault();
|
|
7487
|
+
handleSubmit();
|
|
7488
|
+
}
|
|
7489
|
+
if (e.key === "Escape") {
|
|
7490
|
+
setShowAddForm(false);
|
|
7491
|
+
setNewComment("");
|
|
7492
|
+
}
|
|
7493
|
+
};
|
|
7494
|
+
const formatDate2 = (date) => {
|
|
7495
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
7496
|
+
month: "short",
|
|
7497
|
+
day: "numeric",
|
|
7498
|
+
hour: "numeric",
|
|
7499
|
+
minute: "2-digit"
|
|
7500
|
+
}).format(date);
|
|
7501
|
+
};
|
|
7502
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
7503
|
+
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: [
|
|
7504
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7505
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7506
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
7507
|
+
] }),
|
|
7508
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7509
|
+
] }, comment.id)) }),
|
|
7510
|
+
!showAddForm ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7511
|
+
Button,
|
|
7512
|
+
{
|
|
7513
|
+
variant: "ghost",
|
|
7514
|
+
size: "sm",
|
|
7515
|
+
className: "w-full justify-start gap-2 h-8 text-muted-foreground",
|
|
7516
|
+
onClick: () => setShowAddForm(true),
|
|
7517
|
+
children: [
|
|
7518
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3.5 w-3.5" }),
|
|
7519
|
+
comments.length > 0 ? "Add another comment" : "Add a comment..."
|
|
7520
|
+
]
|
|
7521
|
+
}
|
|
7522
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 animate-in fade-in-0 slide-in-from-top-2 duration-200", children: [
|
|
7523
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7524
|
+
Textarea,
|
|
7525
|
+
{
|
|
7526
|
+
placeholder: "Add a comment...",
|
|
7527
|
+
value: newComment,
|
|
7528
|
+
onChange: (e) => setNewComment(e.target.value),
|
|
7529
|
+
onKeyDown: handleKeyDown,
|
|
7530
|
+
className: "min-h-[60px] text-sm resize-none",
|
|
7531
|
+
autoFocus: true
|
|
7532
|
+
}
|
|
7533
|
+
),
|
|
7534
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7535
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send" }),
|
|
7536
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7537
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7538
|
+
Button,
|
|
7539
|
+
{
|
|
7540
|
+
variant: "ghost",
|
|
7541
|
+
size: "sm",
|
|
7542
|
+
className: "h-7",
|
|
7543
|
+
onClick: () => {
|
|
7544
|
+
setShowAddForm(false);
|
|
7545
|
+
setNewComment("");
|
|
7546
|
+
},
|
|
7547
|
+
children: "Cancel"
|
|
7548
|
+
}
|
|
7549
|
+
),
|
|
7550
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7551
|
+
Button,
|
|
7552
|
+
{
|
|
7553
|
+
size: "sm",
|
|
7554
|
+
className: "h-7 gap-1",
|
|
7555
|
+
onClick: handleSubmit,
|
|
7556
|
+
disabled: !newComment.trim(),
|
|
7557
|
+
children: [
|
|
7558
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
7559
|
+
"Save"
|
|
7560
|
+
]
|
|
7561
|
+
}
|
|
7562
|
+
)
|
|
7563
|
+
] })
|
|
7564
|
+
] })
|
|
7565
|
+
] })
|
|
7566
|
+
] });
|
|
7567
|
+
}
|
|
7568
|
+
function DeliveryListItem({
|
|
7569
|
+
delivery,
|
|
7570
|
+
index,
|
|
7571
|
+
onClick
|
|
7572
|
+
}) {
|
|
7573
|
+
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
7574
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7575
|
+
"button",
|
|
7576
|
+
{
|
|
7577
|
+
onClick,
|
|
7578
|
+
className: cn(
|
|
7579
|
+
"w-full flex items-center justify-between p-3 rounded-lg",
|
|
7580
|
+
"bg-card border hover:bg-muted/50 transition-colors cursor-pointer",
|
|
7581
|
+
"text-left"
|
|
7582
|
+
),
|
|
7583
|
+
children: [
|
|
7584
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7585
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
7586
|
+
"flex items-center justify-center h-8 w-8 rounded-lg",
|
|
7587
|
+
delivery.status === "on-time" && "bg-green-100 dark:bg-green-950/50",
|
|
7588
|
+
delivery.status === "delayed" && "bg-amber-100 dark:bg-amber-950/50",
|
|
7589
|
+
delivery.status === "critical" && "bg-red-100 dark:bg-red-950/50"
|
|
7590
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: cn(
|
|
7591
|
+
"h-4 w-4",
|
|
7592
|
+
delivery.status === "on-time" && "text-green-600 dark:text-green-400",
|
|
7593
|
+
delivery.status === "delayed" && "text-amber-600 dark:text-amber-400",
|
|
7594
|
+
delivery.status === "critical" && "text-red-600 dark:text-red-400"
|
|
7595
|
+
) }) }),
|
|
7596
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7597
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7598
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: delivery.label || `Delivery ${index + 1}` }),
|
|
7599
|
+
hasComments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
7600
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "h-3 w-3 text-muted-foreground" }),
|
|
7601
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-primary" })
|
|
7602
|
+
] })
|
|
7603
|
+
] }),
|
|
7604
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
7605
|
+
"\u2192 ",
|
|
7606
|
+
delivery.destination
|
|
7607
|
+
] })
|
|
7608
|
+
] })
|
|
7609
|
+
] }),
|
|
7610
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7611
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7612
|
+
Badge,
|
|
7613
|
+
{
|
|
7614
|
+
variant: getStatusBadgeVariant(delivery.status),
|
|
7615
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7616
|
+
children: getStatusLabel(delivery.status)
|
|
7617
|
+
}
|
|
7618
|
+
),
|
|
7619
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
7620
|
+
] })
|
|
7621
|
+
]
|
|
7622
|
+
}
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
7625
|
+
function DeliveryDetailsView({
|
|
7626
|
+
delivery,
|
|
7627
|
+
week,
|
|
7628
|
+
onBack,
|
|
7629
|
+
onAddComment
|
|
7630
|
+
}) {
|
|
7631
|
+
const elements = delivery.elements ?? [];
|
|
7632
|
+
const categorizedElements = React22__namespace.useMemo(() => {
|
|
7633
|
+
const sent = [];
|
|
7634
|
+
const notSent = [];
|
|
7635
|
+
const moved = [];
|
|
7636
|
+
const addons = [];
|
|
7637
|
+
elements.forEach((element) => {
|
|
7638
|
+
const status = getElementShipmentStatus(element, delivery.id);
|
|
7639
|
+
switch (status) {
|
|
7640
|
+
case "sent":
|
|
7641
|
+
sent.push(element);
|
|
7642
|
+
break;
|
|
7643
|
+
case "not-sent":
|
|
7644
|
+
notSent.push(element);
|
|
7645
|
+
break;
|
|
7646
|
+
case "moved":
|
|
7647
|
+
moved.push(element);
|
|
7648
|
+
break;
|
|
7649
|
+
case "addon":
|
|
7650
|
+
addons.push(element);
|
|
7651
|
+
break;
|
|
7652
|
+
default:
|
|
7653
|
+
notSent.push(element);
|
|
7654
|
+
}
|
|
7655
|
+
});
|
|
7656
|
+
return { sent, notSent, moved, addons };
|
|
7657
|
+
}, [elements, delivery.id]);
|
|
7658
|
+
const totalCount = elements.length;
|
|
7659
|
+
const sentCount = categorizedElements.sent.length;
|
|
7660
|
+
(delivery.comments?.length ?? 0) > 0;
|
|
7661
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full animate-in slide-in-from-right-4 duration-200", children: [
|
|
7662
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-6 py-3 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7663
|
+
Button,
|
|
7664
|
+
{
|
|
7665
|
+
variant: "ghost",
|
|
7666
|
+
size: "sm",
|
|
7667
|
+
className: "gap-1 -ml-2",
|
|
7668
|
+
onClick: onBack,
|
|
7669
|
+
children: [
|
|
7670
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }),
|
|
7671
|
+
"Back"
|
|
7672
|
+
]
|
|
7673
|
+
}
|
|
7674
|
+
) }),
|
|
7675
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4 space-y-2", children: [
|
|
7676
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7677
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: delivery.label || "Delivery Details" }),
|
|
7678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7679
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7680
|
+
DeliveryCommentPopover,
|
|
7681
|
+
{
|
|
7682
|
+
comments: delivery.comments,
|
|
7683
|
+
onAddComment,
|
|
7684
|
+
deliveryLabel: delivery.label || "Delivery"
|
|
7685
|
+
}
|
|
7686
|
+
),
|
|
7687
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7688
|
+
Badge,
|
|
7689
|
+
{
|
|
7690
|
+
variant: getStatusBadgeVariant(delivery.status),
|
|
7691
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7692
|
+
children: getStatusLabel(delivery.status)
|
|
7693
|
+
}
|
|
7694
|
+
)
|
|
7695
|
+
] })
|
|
7696
|
+
] }),
|
|
7697
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
7698
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
7699
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-3.5 w-3.5" }),
|
|
7700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7701
|
+
week.label,
|
|
7702
|
+
" \u2022 ",
|
|
7703
|
+
week.dateRange
|
|
7704
|
+
] })
|
|
7705
|
+
] }),
|
|
7706
|
+
delivery.destination && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
7707
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-3.5 w-3.5" }),
|
|
7708
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7709
|
+
"\u2192 ",
|
|
7710
|
+
delivery.destination
|
|
7711
|
+
] })
|
|
7712
|
+
] })
|
|
7713
|
+
] })
|
|
7714
|
+
] }),
|
|
7715
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-6 pb-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
7716
|
+
totalCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted/50 p-4", children: [
|
|
7717
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
7718
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Shipment Progress" }),
|
|
7719
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold tabular-nums", children: [
|
|
7720
|
+
"Shipped ",
|
|
7721
|
+
sentCount,
|
|
7722
|
+
" / ",
|
|
7723
|
+
totalCount
|
|
7724
|
+
] })
|
|
7725
|
+
] }),
|
|
7726
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7727
|
+
"div",
|
|
7728
|
+
{
|
|
7729
|
+
className: cn(
|
|
7730
|
+
"h-full rounded-full transition-all",
|
|
7731
|
+
sentCount === totalCount ? "bg-green-500" : "bg-primary"
|
|
7732
|
+
),
|
|
7733
|
+
style: { width: `${totalCount > 0 ? sentCount / totalCount * 100 : 0}%` }
|
|
7734
|
+
}
|
|
7735
|
+
) }),
|
|
7736
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mt-3 flex-wrap", children: [
|
|
7737
|
+
categorizedElements.sent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7738
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-3 w-3 text-green-600" }),
|
|
7739
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-green-700 dark:text-green-300", children: [
|
|
7740
|
+
categorizedElements.sent.length,
|
|
7741
|
+
" Sent"
|
|
7742
|
+
] })
|
|
7743
|
+
] }),
|
|
7744
|
+
categorizedElements.notSent.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7745
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-3 w-3 text-amber-600" }),
|
|
7746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-amber-700 dark:text-amber-300", children: [
|
|
7747
|
+
categorizedElements.notSent.length,
|
|
7748
|
+
" Not sent"
|
|
7749
|
+
] })
|
|
7750
|
+
] }),
|
|
7751
|
+
categorizedElements.moved.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7752
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "h-3 w-3 text-blue-600" }),
|
|
7753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-blue-700 dark:text-blue-300", children: [
|
|
7754
|
+
categorizedElements.moved.length,
|
|
7755
|
+
" Moved"
|
|
7756
|
+
] })
|
|
7757
|
+
] }),
|
|
7758
|
+
categorizedElements.addons.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7759
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3 text-purple-600" }),
|
|
7760
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-700 dark:text-purple-300", children: [
|
|
7761
|
+
categorizedElements.addons.length,
|
|
7762
|
+
" Add-on"
|
|
7763
|
+
] })
|
|
7764
|
+
] })
|
|
7765
|
+
] })
|
|
7766
|
+
] }),
|
|
7767
|
+
elements.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
7768
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Elements" }),
|
|
7769
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
7770
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "bg-sidebar hover:bg-sidebar", children: [
|
|
7771
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Prefix" }),
|
|
7772
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold", children: "Type" }),
|
|
7773
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-right", children: "Weight" }),
|
|
7774
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-right", children: "Size (m\xB2)" }),
|
|
7775
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "font-semibold text-center", children: "Status" })
|
|
7776
|
+
] }) }),
|
|
7777
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: elements.map((element) => {
|
|
7778
|
+
const shipmentStatus = getElementShipmentStatus(element, delivery.id);
|
|
7779
|
+
const statusLabel = getShipmentStatusLabel(shipmentStatus);
|
|
7780
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7781
|
+
TableRow,
|
|
7782
|
+
{
|
|
7783
|
+
className: getShipmentStatusRowBg(shipmentStatus),
|
|
7784
|
+
children: [
|
|
7785
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "font-medium", children: element.prefix || "\u2014" }),
|
|
7786
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: element.type || element.name || "\u2014" }),
|
|
7787
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums", children: element.weight ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7788
|
+
element.weight,
|
|
7789
|
+
" ",
|
|
7790
|
+
element.weightUnit || "kg"
|
|
7791
|
+
] }) : "\u2014" }),
|
|
7792
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "text-right tabular-nums", children: element.sizeSqm ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: element.sizeSqm }) : "\u2014" }),
|
|
7793
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
7794
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7795
|
+
Badge,
|
|
7796
|
+
{
|
|
7797
|
+
variant: "outline",
|
|
7798
|
+
className: cn(
|
|
7799
|
+
"text-[10px] h-5",
|
|
7800
|
+
getShipmentStatusBadgeClasses(shipmentStatus)
|
|
7801
|
+
),
|
|
7802
|
+
children: statusLabel
|
|
7803
|
+
}
|
|
7804
|
+
),
|
|
7805
|
+
shipmentStatus === "moved" && element.actualDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-blue-600 dark:text-blue-400", children: [
|
|
7806
|
+
"\u2192 ",
|
|
7807
|
+
element.actualDeliveryLabel
|
|
7808
|
+
] }),
|
|
7809
|
+
shipmentStatus === "addon" && element.originalDeliveryLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-purple-600 dark:text-purple-400", children: [
|
|
7810
|
+
"from ",
|
|
7811
|
+
element.originalDeliveryLabel
|
|
7812
|
+
] })
|
|
7813
|
+
] }) })
|
|
7814
|
+
]
|
|
7815
|
+
},
|
|
7816
|
+
element.id
|
|
7817
|
+
);
|
|
7818
|
+
}) })
|
|
7819
|
+
] }) })
|
|
7820
|
+
] }),
|
|
7821
|
+
elements.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
7822
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
7823
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No elements in this delivery" })
|
|
7824
|
+
] })
|
|
7825
|
+
] }) })
|
|
7826
|
+
] });
|
|
7827
|
+
}
|
|
7828
|
+
function MainView({
|
|
7829
|
+
supplier,
|
|
7830
|
+
week,
|
|
7831
|
+
data,
|
|
7832
|
+
producedValue,
|
|
7833
|
+
hasChanges,
|
|
7834
|
+
onProducedChange,
|
|
7835
|
+
onSave,
|
|
7836
|
+
onSelectDelivery,
|
|
7837
|
+
onAddProductionComment
|
|
7838
|
+
}) {
|
|
7839
|
+
const production = data?.production;
|
|
7840
|
+
const productionProgress = production ? Math.min(100, Math.round(production.produced / production.target * 100)) : data?.progress ?? 0;
|
|
7841
|
+
const productionStatus = production?.status ?? "on-time";
|
|
7842
|
+
const isComplete = productionProgress >= 100;
|
|
7843
|
+
const hasProductionComments = (production?.comments?.length ?? 0) > 0;
|
|
7844
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-in fade-in-0 duration-200", children: [
|
|
7845
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "px-6 pt-6 pb-4", children: [
|
|
7846
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
7847
|
+
supplier.name,
|
|
7848
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs font-normal", children: supplier.badgeType })
|
|
7849
|
+
] }),
|
|
7850
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { className: "flex items-center gap-2", children: [
|
|
7851
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-4 w-4" }),
|
|
7852
|
+
week.label,
|
|
7853
|
+
" \u2022 ",
|
|
7854
|
+
week.dateRange
|
|
7855
|
+
] })
|
|
7856
|
+
] }),
|
|
7857
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 px-6 pb-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
|
|
7858
|
+
data.type !== "empty" && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
7859
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7860
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Factory, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7861
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Production" }),
|
|
7862
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7863
|
+
Badge,
|
|
7864
|
+
{
|
|
7865
|
+
variant: getStatusBadgeVariant(productionStatus),
|
|
7866
|
+
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus)),
|
|
7867
|
+
children: getStatusLabel(productionStatus)
|
|
7868
|
+
}
|
|
7869
|
+
)
|
|
7870
|
+
] }),
|
|
7871
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-6", children: [
|
|
7872
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7873
|
+
CircularProgress,
|
|
7874
|
+
{
|
|
7875
|
+
value: productionProgress,
|
|
7876
|
+
size: 100,
|
|
7877
|
+
strokeWidth: 10,
|
|
7878
|
+
variant: getProgressVariant(productionStatus),
|
|
7879
|
+
showCheckmark: isComplete,
|
|
7880
|
+
children: isComplete ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7881
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-6 w-6 text-green-600" }),
|
|
7882
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-green-600", children: [
|
|
7883
|
+
production?.produced ?? 0,
|
|
7884
|
+
" ",
|
|
7885
|
+
production ? formatProductionUnit(production.unit) : ""
|
|
7886
|
+
] })
|
|
7887
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7888
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold tabular-nums", children: production?.produced ?? 0 }),
|
|
7889
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
7890
|
+
"/ ",
|
|
7891
|
+
production?.target ?? 0,
|
|
7892
|
+
" ",
|
|
7893
|
+
production ? formatProductionUnit(production.unit) : ""
|
|
7894
|
+
] })
|
|
7895
|
+
] })
|
|
7896
|
+
}
|
|
7897
|
+
),
|
|
7898
|
+
production && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
7899
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
7900
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label2, { htmlFor: "produced", className: "text-xs", children: [
|
|
7901
|
+
"Produced Amount (",
|
|
7902
|
+
formatProductionUnit(production.unit),
|
|
7903
|
+
")"
|
|
7904
|
+
] }),
|
|
7905
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7906
|
+
Input,
|
|
7907
|
+
{
|
|
7908
|
+
id: "produced",
|
|
7909
|
+
type: "number",
|
|
7910
|
+
min: "0",
|
|
7911
|
+
max: production.target * 2,
|
|
7912
|
+
value: producedValue,
|
|
7913
|
+
onChange: onProducedChange,
|
|
7914
|
+
className: "h-9"
|
|
7915
|
+
}
|
|
7916
|
+
) }),
|
|
7917
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
|
|
7918
|
+
"Target: ",
|
|
7919
|
+
production.target,
|
|
7920
|
+
" ",
|
|
7921
|
+
formatProductionUnit(production.unit)
|
|
7922
|
+
] })
|
|
7923
|
+
] }),
|
|
7924
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7925
|
+
Button,
|
|
7926
|
+
{
|
|
7927
|
+
size: "sm",
|
|
7928
|
+
className: "w-full",
|
|
7929
|
+
disabled: !hasChanges,
|
|
7930
|
+
onClick: onSave,
|
|
7931
|
+
children: hasChanges ? "Save Progress" : "No Changes"
|
|
7932
|
+
}
|
|
7933
|
+
)
|
|
7934
|
+
] })
|
|
7935
|
+
] }),
|
|
7936
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
7937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7938
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Comments" }),
|
|
7939
|
+
hasProductionComments && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
7940
|
+
"(",
|
|
7941
|
+
production?.comments?.length,
|
|
7942
|
+
")"
|
|
7943
|
+
] })
|
|
7944
|
+
] }),
|
|
7945
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7946
|
+
ProductionCommentSection,
|
|
7947
|
+
{
|
|
7948
|
+
comments: production?.comments,
|
|
7949
|
+
onAddComment: onAddProductionComment
|
|
7950
|
+
}
|
|
7951
|
+
)
|
|
7952
|
+
] })
|
|
7953
|
+
] }),
|
|
7954
|
+
data.deliveries && data.deliveries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
7955
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7956
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7957
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Deliveries" }),
|
|
7958
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground ml-auto", children: [
|
|
7959
|
+
data.deliveries.length,
|
|
7960
|
+
" scheduled"
|
|
7961
|
+
] })
|
|
7962
|
+
] }),
|
|
7963
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: data.deliveries.map((delivery, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7964
|
+
DeliveryListItem,
|
|
7965
|
+
{
|
|
7966
|
+
delivery,
|
|
7967
|
+
index,
|
|
7968
|
+
onClick: () => onSelectDelivery(delivery)
|
|
7969
|
+
},
|
|
7970
|
+
delivery.id
|
|
7971
|
+
)) })
|
|
7972
|
+
] }),
|
|
7973
|
+
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: [
|
|
7974
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Truck, { className: "h-4 w-4" }),
|
|
7975
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "No logistics scheduled for this week" })
|
|
7976
|
+
] }),
|
|
7977
|
+
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: [
|
|
7978
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }),
|
|
7979
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm", children: data.warningMessage })
|
|
7980
|
+
] }),
|
|
7981
|
+
data.notes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
7982
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Notes" }),
|
|
7983
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: data.notes })
|
|
7984
|
+
] })
|
|
7985
|
+
] }) })
|
|
7986
|
+
] });
|
|
7987
|
+
}
|
|
7988
|
+
function WeekDetailDialog({
|
|
7989
|
+
open,
|
|
7990
|
+
onOpenChange,
|
|
7991
|
+
supplier,
|
|
7992
|
+
week,
|
|
7993
|
+
data,
|
|
7994
|
+
onProgressUpdate,
|
|
7995
|
+
onAddProductionComment,
|
|
7996
|
+
onAddDeliveryComment
|
|
7997
|
+
}) {
|
|
7998
|
+
const production = data?.production;
|
|
7999
|
+
const initialProduced = production?.produced ?? 0;
|
|
8000
|
+
const [producedValue, setProducedValue] = React22__namespace.useState(initialProduced.toString());
|
|
8001
|
+
const [hasChanges, setHasChanges] = React22__namespace.useState(false);
|
|
8002
|
+
const [selectedDelivery, setSelectedDelivery] = React22__namespace.useState(null);
|
|
8003
|
+
React22__namespace.useEffect(() => {
|
|
8004
|
+
const newProduced = data?.production?.produced ?? 0;
|
|
8005
|
+
setProducedValue(newProduced.toString());
|
|
8006
|
+
setHasChanges(false);
|
|
8007
|
+
}, [data]);
|
|
8008
|
+
React22__namespace.useEffect(() => {
|
|
8009
|
+
if (!open) {
|
|
8010
|
+
setSelectedDelivery(null);
|
|
8011
|
+
}
|
|
8012
|
+
}, [open]);
|
|
8013
|
+
const handleProducedChange = (e) => {
|
|
8014
|
+
const value = e.target.value;
|
|
8015
|
+
setProducedValue(value);
|
|
8016
|
+
setHasChanges(true);
|
|
8017
|
+
};
|
|
8018
|
+
const handleSave = () => {
|
|
8019
|
+
if (!supplier || !week || !onProgressUpdate) return;
|
|
8020
|
+
const newProduced = parseFloat(producedValue) || 0;
|
|
8021
|
+
const target = production?.target || 100;
|
|
8022
|
+
const newProgress = Math.min(100, Math.round(newProduced / target * 100));
|
|
8023
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
8024
|
+
onProgressUpdate(supplier.id, weekKey, newProgress, newProduced);
|
|
8025
|
+
setHasChanges(false);
|
|
8026
|
+
};
|
|
8027
|
+
if (!supplier || !week || !data) {
|
|
8028
|
+
return null;
|
|
8029
|
+
}
|
|
8030
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContent, { className: "max-w-lg max-h-[85vh] p-0 gap-0 overflow-hidden", children: selectedDelivery ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8031
|
+
DeliveryDetailsView,
|
|
8032
|
+
{
|
|
8033
|
+
delivery: selectedDelivery,
|
|
8034
|
+
week,
|
|
8035
|
+
onBack: () => setSelectedDelivery(null),
|
|
8036
|
+
onAddComment: onAddDeliveryComment ? (text) => {
|
|
8037
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
8038
|
+
onAddDeliveryComment(supplier.id, weekKey, selectedDelivery.id, text);
|
|
8039
|
+
} : void 0
|
|
8040
|
+
}
|
|
8041
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8042
|
+
MainView,
|
|
8043
|
+
{
|
|
8044
|
+
supplier,
|
|
8045
|
+
week,
|
|
8046
|
+
data,
|
|
8047
|
+
producedValue,
|
|
8048
|
+
hasChanges,
|
|
8049
|
+
onProducedChange: handleProducedChange,
|
|
8050
|
+
onSave: handleSave,
|
|
8051
|
+
onSelectDelivery: setSelectedDelivery,
|
|
8052
|
+
onAddProductionComment: onAddProductionComment ? (text) => {
|
|
8053
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
8054
|
+
onAddProductionComment(supplier.id, weekKey, text);
|
|
8055
|
+
} : void 0
|
|
8056
|
+
}
|
|
8057
|
+
) }) });
|
|
8058
|
+
}
|
|
8059
|
+
function RowHeaderCell({
|
|
8060
|
+
className,
|
|
8061
|
+
data,
|
|
8062
|
+
showProgress = true,
|
|
8063
|
+
...props
|
|
8064
|
+
}) {
|
|
8065
|
+
const progressPercent = data.totalRequired > 0 ? Math.min(data.totalBooked / data.totalRequired * 100, 100) : 0;
|
|
8066
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8067
|
+
"div",
|
|
8068
|
+
{
|
|
8069
|
+
"data-slot": "row-header-cell",
|
|
8070
|
+
className: cn(
|
|
8071
|
+
"flex flex-col justify-center gap-1.5 py-2 px-3 min-w-[200px] h-[100px] bg-background",
|
|
8072
|
+
className
|
|
8073
|
+
),
|
|
8074
|
+
...props,
|
|
8075
|
+
children: [
|
|
8076
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
8077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
8078
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: data.name }),
|
|
8079
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: data.typeCode })
|
|
8080
|
+
] }),
|
|
8081
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8082
|
+
Badge,
|
|
8083
|
+
{
|
|
8084
|
+
variant: "outline",
|
|
8085
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
8086
|
+
children: [
|
|
8087
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Flag, { className: "h-2.5 w-2.5" }),
|
|
8088
|
+
"Paint"
|
|
8089
|
+
]
|
|
8090
|
+
}
|
|
8091
|
+
)
|
|
8092
|
+
] }),
|
|
8093
|
+
showProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
8094
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8095
|
+
"div",
|
|
8096
|
+
{
|
|
8097
|
+
className: "h-full bg-primary rounded-full transition-all",
|
|
8098
|
+
style: { width: `${progressPercent}%` }
|
|
8099
|
+
}
|
|
8100
|
+
) }),
|
|
8101
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-primary", children: [
|
|
8102
|
+
data.totalBooked.toLocaleString(),
|
|
8103
|
+
" / ",
|
|
8104
|
+
data.totalRequired.toLocaleString(),
|
|
8105
|
+
" Booked"
|
|
8106
|
+
] })
|
|
8107
|
+
] })
|
|
8108
|
+
]
|
|
8109
|
+
}
|
|
8110
|
+
);
|
|
8111
|
+
}
|
|
8112
|
+
function NetBadge({
|
|
8113
|
+
className,
|
|
8114
|
+
net,
|
|
8115
|
+
status,
|
|
8116
|
+
compact = false,
|
|
8117
|
+
...props
|
|
8118
|
+
}) {
|
|
8119
|
+
const statusStyles = {
|
|
8120
|
+
pending: {
|
|
8121
|
+
container: "bg-muted border-border/50",
|
|
8122
|
+
text: "text-muted-foreground",
|
|
8123
|
+
icon: "text-muted-foreground"
|
|
8124
|
+
},
|
|
8125
|
+
valid: {
|
|
8126
|
+
container: "bg-green-100/50 border-green-500 dark:bg-green-950/30 dark:border-green-400",
|
|
8127
|
+
text: "text-green-700 dark:text-green-400",
|
|
8128
|
+
icon: "text-green-600 dark:text-green-400"
|
|
8129
|
+
},
|
|
8130
|
+
shortfall: {
|
|
8131
|
+
container: "bg-red-100/30 border-red-400/50 dark:bg-red-950/30 dark:border-red-400/50",
|
|
8132
|
+
text: "text-red-700 dark:text-red-400",
|
|
8133
|
+
icon: "text-red-600 dark:text-red-400"
|
|
8134
|
+
}
|
|
8135
|
+
};
|
|
8136
|
+
const styles = statusStyles[status];
|
|
8137
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8138
|
+
"div",
|
|
8139
|
+
{
|
|
8140
|
+
"data-slot": "net-badge",
|
|
8141
|
+
"data-status": status,
|
|
8142
|
+
className: cn(
|
|
8143
|
+
"inline-flex items-center gap-1.5 px-3 py-0.5 rounded-full border",
|
|
8144
|
+
styles.container,
|
|
8145
|
+
className
|
|
8146
|
+
),
|
|
8147
|
+
...props,
|
|
8148
|
+
children: [
|
|
8149
|
+
status === "valid" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-3 w-3", styles.icon) }),
|
|
8150
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
8151
|
+
"text-xs font-bold leading-none",
|
|
8152
|
+
styles.text
|
|
8153
|
+
), children: net >= 0 ? net : net }),
|
|
8154
|
+
!compact && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
8155
|
+
"text-[10px] font-light opacity-80",
|
|
8156
|
+
styles.text
|
|
8157
|
+
), children: "net" })
|
|
8158
|
+
]
|
|
8159
|
+
}
|
|
8160
|
+
);
|
|
8161
|
+
}
|
|
8162
|
+
|
|
8163
|
+
// src/blocks/calibration-table/types.ts
|
|
8164
|
+
function formatCalibrationUnit(unit) {
|
|
8165
|
+
const unitLabels = {
|
|
8166
|
+
ton: "tons",
|
|
8167
|
+
pcs: "pcs",
|
|
8168
|
+
m2: "m\xB2",
|
|
8169
|
+
kg: "kg",
|
|
8170
|
+
m: "m"
|
|
8171
|
+
};
|
|
8172
|
+
return unitLabels[unit] || unit;
|
|
8173
|
+
}
|
|
8174
|
+
function calculateCalibrationCells(weeks) {
|
|
8175
|
+
const result = {};
|
|
8176
|
+
let accumulatedPlanned = 0;
|
|
8177
|
+
let accumulatedEntered = 0;
|
|
8178
|
+
for (const week of weeks) {
|
|
8179
|
+
accumulatedPlanned += week.planned;
|
|
8180
|
+
accumulatedEntered += week.entered ?? 0;
|
|
8181
|
+
const net = accumulatedEntered - accumulatedPlanned;
|
|
8182
|
+
let status = "pending";
|
|
8183
|
+
if (week.entered !== null) {
|
|
8184
|
+
status = net >= 0 ? "valid" : "shortfall";
|
|
8185
|
+
}
|
|
8186
|
+
result[week.weekKey] = {
|
|
8187
|
+
planned: week.planned,
|
|
8188
|
+
entered: week.entered,
|
|
8189
|
+
accumulatedPlanned,
|
|
8190
|
+
accumulatedEntered,
|
|
8191
|
+
net,
|
|
8192
|
+
status,
|
|
8193
|
+
isEditable: true
|
|
8194
|
+
};
|
|
8195
|
+
}
|
|
8196
|
+
return result;
|
|
8197
|
+
}
|
|
8198
|
+
function canSubmitCalibration(prefixes) {
|
|
8199
|
+
let shortfallCount = 0;
|
|
8200
|
+
let pendingCount = 0;
|
|
8201
|
+
for (const prefix of prefixes) {
|
|
8202
|
+
for (const weekKey in prefix.weeks) {
|
|
8203
|
+
const cell = prefix.weeks[weekKey];
|
|
8204
|
+
if (cell.status === "shortfall") shortfallCount++;
|
|
8205
|
+
if (cell.status === "pending") pendingCount++;
|
|
8206
|
+
}
|
|
8207
|
+
}
|
|
8208
|
+
const canSubmit = shortfallCount === 0 && pendingCount === 0;
|
|
8209
|
+
let message = "";
|
|
8210
|
+
if (shortfallCount > 0) {
|
|
8211
|
+
message = `Resolve ${shortfallCount} shortfall${shortfallCount > 1 ? "s" : ""} to submit`;
|
|
8212
|
+
} else if (pendingCount > 0) {
|
|
8213
|
+
message = `Enter production amounts for ${pendingCount} week${pendingCount > 1 ? "s" : ""}`;
|
|
8214
|
+
} else {
|
|
8215
|
+
message = "Ready to submit";
|
|
8216
|
+
}
|
|
8217
|
+
return { canSubmit, shortfallCount, pendingCount, message };
|
|
8218
|
+
}
|
|
8219
|
+
function CalibrationWeekCell({
|
|
8220
|
+
className,
|
|
8221
|
+
data,
|
|
8222
|
+
unit,
|
|
8223
|
+
onValueChange,
|
|
8224
|
+
isFocused,
|
|
8225
|
+
forcedRed = false,
|
|
8226
|
+
isEmpty = false,
|
|
8227
|
+
onAddClick,
|
|
8228
|
+
...props
|
|
8229
|
+
}) {
|
|
8230
|
+
const inputRef = React22__namespace.useRef(null);
|
|
8231
|
+
const [localValue, setLocalValue] = React22__namespace.useState(
|
|
8232
|
+
data.entered !== null ? String(data.entered) : ""
|
|
8233
|
+
);
|
|
8234
|
+
const [isHovered, setIsHovered] = React22__namespace.useState(false);
|
|
8235
|
+
const [isEditing, setIsEditing] = React22__namespace.useState(false);
|
|
8236
|
+
React22__namespace.useEffect(() => {
|
|
8237
|
+
setLocalValue(data.entered !== null ? String(data.entered) : "");
|
|
8238
|
+
}, [data.entered]);
|
|
8239
|
+
const unitLabel = formatCalibrationUnit(unit);
|
|
8240
|
+
const effectiveStatus = forcedRed ? "forcedRed" : data.status;
|
|
8241
|
+
const handleInputChange = (e) => {
|
|
8242
|
+
const val = e.target.value;
|
|
8243
|
+
setLocalValue(val);
|
|
8244
|
+
if (val === "" || val === "-") {
|
|
8245
|
+
onValueChange?.(null);
|
|
8246
|
+
} else {
|
|
8247
|
+
const numVal = parseFloat(val);
|
|
8248
|
+
if (!isNaN(numVal)) {
|
|
8249
|
+
onValueChange?.(numVal);
|
|
8250
|
+
}
|
|
8251
|
+
}
|
|
8252
|
+
};
|
|
8253
|
+
const handleBlur = () => {
|
|
8254
|
+
setIsEditing(false);
|
|
8255
|
+
if (localValue === "" || localValue === "-") {
|
|
8256
|
+
setLocalValue("");
|
|
8257
|
+
onValueChange?.(null);
|
|
8258
|
+
} else {
|
|
8259
|
+
const numVal = parseFloat(localValue);
|
|
8260
|
+
if (!isNaN(numVal)) {
|
|
8261
|
+
setLocalValue(String(numVal));
|
|
8262
|
+
onValueChange?.(numVal);
|
|
8263
|
+
}
|
|
8264
|
+
}
|
|
8265
|
+
};
|
|
8266
|
+
const handleAddClick = () => {
|
|
8267
|
+
setIsEditing(true);
|
|
8268
|
+
onAddClick?.();
|
|
8269
|
+
setTimeout(() => {
|
|
8270
|
+
inputRef.current?.focus();
|
|
8271
|
+
}, 0);
|
|
8272
|
+
};
|
|
8273
|
+
const getContainerStyles = () => {
|
|
8274
|
+
switch (effectiveStatus) {
|
|
8275
|
+
case "valid":
|
|
8276
|
+
return "border-l-2 border-l-green-500 bg-green-50/50 dark:bg-green-950/30";
|
|
8277
|
+
case "shortfall":
|
|
8278
|
+
case "forcedRed":
|
|
8279
|
+
return "border-l-2 border-l-red-500 bg-red-50/50 dark:bg-red-950/30";
|
|
8280
|
+
case "pending":
|
|
8281
|
+
default:
|
|
8282
|
+
return cn(
|
|
8283
|
+
"bg-background",
|
|
8284
|
+
isHovered ? "border-l-2 border-l-border" : "border-l-2 border-l-transparent"
|
|
8285
|
+
);
|
|
8286
|
+
}
|
|
8287
|
+
};
|
|
8288
|
+
const getInputStyles = () => {
|
|
8289
|
+
switch (effectiveStatus) {
|
|
8290
|
+
case "valid":
|
|
8291
|
+
return "text-green-700 dark:text-green-400";
|
|
8292
|
+
case "shortfall":
|
|
8293
|
+
case "forcedRed":
|
|
8294
|
+
return "text-red-700 dark:text-red-400 font-semibold";
|
|
8295
|
+
default:
|
|
8296
|
+
return "text-foreground";
|
|
8297
|
+
}
|
|
8298
|
+
};
|
|
8299
|
+
const showAddButton = isEmpty && effectiveStatus === "pending" && !isEditing && data.entered === null;
|
|
8300
|
+
if (showAddButton) {
|
|
8301
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8302
|
+
"div",
|
|
8303
|
+
{
|
|
8304
|
+
"data-slot": "calibration-week-cell",
|
|
8305
|
+
"data-status": "empty",
|
|
8306
|
+
className: cn(
|
|
8307
|
+
"flex items-center justify-center h-[100px]",
|
|
8308
|
+
"transition-all duration-200 ease-out",
|
|
8309
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8310
|
+
"bg-background",
|
|
8311
|
+
isHovered ? "border-l-2 border-l-border" : "border-l-2 border-l-transparent",
|
|
8312
|
+
className
|
|
8313
|
+
),
|
|
8314
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8315
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8316
|
+
...props,
|
|
8317
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8318
|
+
Button,
|
|
8319
|
+
{
|
|
8320
|
+
variant: "ghost",
|
|
8321
|
+
size: "icon",
|
|
8322
|
+
className: cn(
|
|
8323
|
+
"h-10 w-10 rounded-full",
|
|
8324
|
+
"text-muted-foreground/40 hover:text-muted-foreground hover:bg-muted/50",
|
|
8325
|
+
"transition-all duration-200",
|
|
8326
|
+
"shadow-[var(--j3m-shadow-sm)]"
|
|
8327
|
+
),
|
|
8328
|
+
onClick: handleAddClick,
|
|
8329
|
+
children: [
|
|
8330
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-5 w-5" }),
|
|
8331
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add production amount" })
|
|
8332
|
+
]
|
|
8333
|
+
}
|
|
8334
|
+
)
|
|
8335
|
+
}
|
|
8336
|
+
);
|
|
8337
|
+
}
|
|
8338
|
+
if (isEmpty && forcedRed) {
|
|
8339
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8340
|
+
"div",
|
|
8341
|
+
{
|
|
8342
|
+
"data-slot": "calibration-week-cell",
|
|
8343
|
+
"data-status": "forcedRed",
|
|
8344
|
+
className: cn(
|
|
8345
|
+
"flex flex-col items-center justify-center gap-2 h-[100px] px-3 py-2",
|
|
8346
|
+
"transition-all duration-200 ease-out",
|
|
8347
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8348
|
+
"border-l-2 border-l-red-500 bg-red-50/50 dark:bg-red-950/30",
|
|
8349
|
+
className
|
|
8350
|
+
),
|
|
8351
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8352
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8353
|
+
...props,
|
|
8354
|
+
children: [
|
|
8355
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-red-600 dark:text-red-400 text-center", children: "Behind schedule" }),
|
|
8356
|
+
/* @__PURE__ */ jsxRuntime.jsx(NetBadge, { net: data.net, status: "shortfall" })
|
|
8357
|
+
]
|
|
8358
|
+
}
|
|
8359
|
+
);
|
|
8360
|
+
}
|
|
8361
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8362
|
+
"div",
|
|
8363
|
+
{
|
|
8364
|
+
"data-slot": "calibration-week-cell",
|
|
8365
|
+
"data-status": effectiveStatus,
|
|
8366
|
+
className: cn(
|
|
8367
|
+
"flex flex-col gap-2 px-3 py-2 h-[100px]",
|
|
8368
|
+
// Hover lift effect with shadow (like planning table)
|
|
8369
|
+
"transition-all duration-200 ease-out",
|
|
8370
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8371
|
+
getContainerStyles(),
|
|
8372
|
+
className
|
|
8373
|
+
),
|
|
8374
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8375
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8376
|
+
...props,
|
|
8377
|
+
children: [
|
|
8378
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8379
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground tracking-wide", children: "Accumulated" }),
|
|
8380
|
+
/* @__PURE__ */ jsxRuntime.jsx(NetBadge, { net: data.net, status: forcedRed ? "shortfall" : data.status })
|
|
8381
|
+
] }),
|
|
8382
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8383
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground tracking-wide", children: "Planned" }),
|
|
8384
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center px-2 py-0 bg-card border border-border rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground", children: data.planned }) })
|
|
8385
|
+
] }),
|
|
8386
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
8387
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8388
|
+
Input,
|
|
8389
|
+
{
|
|
8390
|
+
ref: inputRef,
|
|
8391
|
+
type: "text",
|
|
8392
|
+
inputMode: "decimal",
|
|
8393
|
+
value: localValue,
|
|
8394
|
+
onChange: handleInputChange,
|
|
8395
|
+
onBlur: handleBlur,
|
|
8396
|
+
onFocus: () => setIsEditing(true),
|
|
8397
|
+
disabled: !data.isEditable,
|
|
8398
|
+
placeholder: "Enter amount",
|
|
8399
|
+
className: cn(
|
|
8400
|
+
"h-8 pl-3 pr-12 rounded-full text-sm font-semibold bg-background border-border",
|
|
8401
|
+
// Placeholder: smaller, lighter, lower contrast
|
|
8402
|
+
"placeholder:text-xs placeholder:font-normal placeholder:text-muted-foreground/50",
|
|
8403
|
+
getInputStyles(),
|
|
8404
|
+
!data.isEditable && "opacity-50 cursor-not-allowed"
|
|
8405
|
+
)
|
|
8406
|
+
}
|
|
8407
|
+
),
|
|
8408
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute right-4 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground/70 pointer-events-none", children: unitLabel })
|
|
8409
|
+
] })
|
|
8410
|
+
]
|
|
8411
|
+
}
|
|
8412
|
+
);
|
|
8413
|
+
}
|
|
8414
|
+
function CommentPopover({
|
|
8415
|
+
comments,
|
|
8416
|
+
weekLabel,
|
|
8417
|
+
availablePrefixes,
|
|
8418
|
+
onAddComment,
|
|
8419
|
+
open,
|
|
8420
|
+
onOpenChange
|
|
8421
|
+
}) {
|
|
8422
|
+
const [newCommentText, setNewCommentText] = React22__namespace.useState("");
|
|
8423
|
+
const [selectedPrefixId, setSelectedPrefixId] = React22__namespace.useState("");
|
|
8424
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22__namespace.useState(true);
|
|
8425
|
+
const [showAddForm, setShowAddForm] = React22__namespace.useState(false);
|
|
8426
|
+
const selectedPrefixName = React22__namespace.useMemo(() => {
|
|
8427
|
+
const prefix = availablePrefixes.find((p) => p.id === selectedPrefixId);
|
|
8428
|
+
return prefix?.name ?? "";
|
|
8429
|
+
}, [availablePrefixes, selectedPrefixId]);
|
|
8430
|
+
const handleSubmit = () => {
|
|
8431
|
+
if (newCommentText.trim() && selectedPrefixId) {
|
|
8432
|
+
onAddComment?.(newCommentText.trim(), selectedPrefixId, selectedPrefixName);
|
|
8433
|
+
setNewCommentText("");
|
|
8434
|
+
setSelectedPrefixId("");
|
|
8435
|
+
setShowAddForm(false);
|
|
8436
|
+
setViewCommentsOpen(true);
|
|
8437
|
+
}
|
|
8438
|
+
};
|
|
8439
|
+
const handleKeyDown = (e) => {
|
|
8440
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
8441
|
+
e.preventDefault();
|
|
8442
|
+
handleSubmit();
|
|
8443
|
+
}
|
|
8444
|
+
if (e.key === "Escape") {
|
|
8445
|
+
setShowAddForm(false);
|
|
8446
|
+
setSelectedPrefixId("");
|
|
8447
|
+
setNewCommentText("");
|
|
8448
|
+
}
|
|
8449
|
+
};
|
|
8450
|
+
const formatDate2 = (date) => {
|
|
8451
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
8452
|
+
month: "short",
|
|
8453
|
+
day: "numeric",
|
|
8454
|
+
hour: "numeric",
|
|
8455
|
+
minute: "2-digit"
|
|
8456
|
+
}).format(date);
|
|
8457
|
+
};
|
|
8458
|
+
const prevOpenRef = React22__namespace.useRef(open);
|
|
8459
|
+
React22__namespace.useEffect(() => {
|
|
8460
|
+
const wasOpen = prevOpenRef.current;
|
|
8461
|
+
prevOpenRef.current = open;
|
|
8462
|
+
if (wasOpen && !open) {
|
|
8463
|
+
setShowAddForm(false);
|
|
8464
|
+
setNewCommentText("");
|
|
8465
|
+
setSelectedPrefixId("");
|
|
8466
|
+
}
|
|
8467
|
+
}, [open]);
|
|
8468
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange, children: [
|
|
8469
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(CommentButton, { commentCount: comments.length }) }),
|
|
8470
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8471
|
+
PopoverContent,
|
|
8472
|
+
{
|
|
8473
|
+
className: "w-80 p-0 z-[100]",
|
|
8474
|
+
align: "end",
|
|
8475
|
+
sideOffset: 8,
|
|
8476
|
+
collisionPadding: 16,
|
|
8477
|
+
children: [
|
|
8478
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
8479
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
8480
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: weekLabel })
|
|
8481
|
+
] }),
|
|
8482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
8483
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
8484
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8485
|
+
Button,
|
|
8486
|
+
{
|
|
8487
|
+
variant: "ghost",
|
|
8488
|
+
size: "sm",
|
|
8489
|
+
className: "w-full justify-between h-8 px-2",
|
|
8490
|
+
children: [
|
|
8491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium", children: [
|
|
8492
|
+
"Comments ",
|
|
8493
|
+
comments.length > 0 && `(${comments.length})`
|
|
8494
|
+
] }),
|
|
8495
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
|
|
8496
|
+
"h-4 w-4 transition-transform duration-200",
|
|
8497
|
+
viewCommentsOpen && "rotate-180"
|
|
8498
|
+
) })
|
|
8499
|
+
]
|
|
8500
|
+
}
|
|
8501
|
+
) }),
|
|
8502
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8503
|
+
"div",
|
|
8504
|
+
{
|
|
8505
|
+
className: "rounded-lg bg-muted/50 p-3 space-y-2",
|
|
8506
|
+
"aria-label": `Comment by ${comment.author} about ${comment.prefixName}`,
|
|
8507
|
+
children: [
|
|
8508
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8509
|
+
Badge,
|
|
8510
|
+
{
|
|
8511
|
+
variant: "outline",
|
|
8512
|
+
className: "text-[10px] px-2 py-0 h-5 font-medium bg-background",
|
|
8513
|
+
children: comment.prefixName
|
|
8514
|
+
}
|
|
8515
|
+
),
|
|
8516
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8517
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
8518
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
8519
|
+
] }),
|
|
8520
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
8521
|
+
]
|
|
8522
|
+
},
|
|
8523
|
+
comment.id
|
|
8524
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
8525
|
+
] }),
|
|
8526
|
+
/* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-2" }),
|
|
8527
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden", children: !showAddForm ? (
|
|
8528
|
+
/* Add comment Button */
|
|
8529
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8530
|
+
Button,
|
|
8531
|
+
{
|
|
8532
|
+
variant: "outline",
|
|
8533
|
+
size: "sm",
|
|
8534
|
+
className: "w-full justify-center gap-2 h-8",
|
|
8535
|
+
onClick: () => setShowAddForm(true),
|
|
8536
|
+
children: [
|
|
8537
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
8538
|
+
"Add comment"
|
|
8539
|
+
]
|
|
8540
|
+
}
|
|
8541
|
+
)
|
|
8542
|
+
) : (
|
|
8543
|
+
/* Comment input form with smooth expand animation */
|
|
8544
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8545
|
+
"div",
|
|
8546
|
+
{
|
|
8547
|
+
className: cn(
|
|
8548
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
8549
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
8550
|
+
),
|
|
8551
|
+
children: [
|
|
8552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
8553
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Label2, { htmlFor: "prefix-select", className: "text-xs font-medium", children: [
|
|
8554
|
+
"Applies to ",
|
|
8555
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive", children: "*" })
|
|
8556
|
+
] }),
|
|
8557
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedPrefixId, onValueChange: setSelectedPrefixId, children: [
|
|
8558
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: "prefix-select", size: "sm", className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select row/type..." }) }),
|
|
8559
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: availablePrefixes.map((prefix) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: prefix.id, children: prefix.name }, prefix.id)) })
|
|
8560
|
+
] })
|
|
8561
|
+
] }),
|
|
8562
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
8563
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "comment-text", className: "text-xs font-medium", children: "Comment" }),
|
|
8564
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8565
|
+
Textarea,
|
|
8566
|
+
{
|
|
8567
|
+
id: "comment-text",
|
|
8568
|
+
placeholder: "Type your comment...",
|
|
8569
|
+
value: newCommentText,
|
|
8570
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
8571
|
+
onKeyDown: handleKeyDown,
|
|
8572
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
8573
|
+
autoFocus: true
|
|
8574
|
+
}
|
|
8575
|
+
)
|
|
8576
|
+
] }),
|
|
8577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8578
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
8579
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8580
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8581
|
+
Button,
|
|
8582
|
+
{
|
|
8583
|
+
variant: "ghost",
|
|
8584
|
+
size: "sm",
|
|
8585
|
+
className: "h-7",
|
|
8586
|
+
onClick: () => {
|
|
8587
|
+
setShowAddForm(false);
|
|
8588
|
+
setNewCommentText("");
|
|
8589
|
+
setSelectedPrefixId("");
|
|
8590
|
+
},
|
|
8591
|
+
children: "Cancel"
|
|
8592
|
+
}
|
|
8593
|
+
),
|
|
8594
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8595
|
+
Button,
|
|
8596
|
+
{
|
|
8597
|
+
size: "sm",
|
|
8598
|
+
className: "h-7 gap-1",
|
|
8599
|
+
onClick: handleSubmit,
|
|
8600
|
+
disabled: !newCommentText.trim() || !selectedPrefixId,
|
|
8601
|
+
children: [
|
|
8602
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3 w-3" }),
|
|
8603
|
+
"Save"
|
|
8604
|
+
]
|
|
8605
|
+
}
|
|
8606
|
+
)
|
|
8607
|
+
] })
|
|
8608
|
+
] })
|
|
8609
|
+
]
|
|
8610
|
+
}
|
|
8611
|
+
)
|
|
8612
|
+
) })
|
|
8613
|
+
] })
|
|
8614
|
+
]
|
|
8615
|
+
}
|
|
8616
|
+
)
|
|
8617
|
+
] });
|
|
8618
|
+
}
|
|
8619
|
+
function CalibrationWeekHeader({
|
|
8620
|
+
className,
|
|
8621
|
+
week,
|
|
8622
|
+
comments = [],
|
|
8623
|
+
showCommentButton = true,
|
|
8624
|
+
availablePrefixes = [],
|
|
8625
|
+
onAddComment,
|
|
8626
|
+
...props
|
|
8627
|
+
}) {
|
|
8628
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8629
|
+
"div",
|
|
8630
|
+
{
|
|
8631
|
+
"data-slot": "calibration-week-header",
|
|
8632
|
+
"data-current-week": week.isCurrentWeek,
|
|
8633
|
+
className: cn(
|
|
8634
|
+
"flex items-center justify-between gap-2 px-2 py-2 min-w-[200px]",
|
|
8635
|
+
className
|
|
8636
|
+
),
|
|
8637
|
+
...props,
|
|
8638
|
+
children: [
|
|
8639
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
8640
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8641
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
8642
|
+
"text-sm font-semibold tracking-tight",
|
|
8643
|
+
week.isCurrentWeek ? "text-primary" : "text-foreground"
|
|
8644
|
+
), children: week.label }),
|
|
8645
|
+
week.isCurrentWeek && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
8646
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75" }),
|
|
8647
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary" })
|
|
8648
|
+
] })
|
|
8649
|
+
] }),
|
|
8650
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-normal text-muted-foreground/60", children: week.dateRange })
|
|
8651
|
+
] }),
|
|
8652
|
+
showCommentButton && availablePrefixes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8653
|
+
CommentPopover,
|
|
8654
|
+
{
|
|
8655
|
+
comments,
|
|
8656
|
+
weekLabel: week.label,
|
|
8657
|
+
availablePrefixes,
|
|
8658
|
+
onAddComment
|
|
8659
|
+
}
|
|
8660
|
+
)
|
|
8661
|
+
]
|
|
8662
|
+
}
|
|
8663
|
+
);
|
|
8664
|
+
}
|
|
8665
|
+
function CalibrationTable({
|
|
8666
|
+
className,
|
|
8667
|
+
prefixes,
|
|
8668
|
+
supplierName,
|
|
8669
|
+
status = "draft",
|
|
8670
|
+
config = {}
|
|
8671
|
+
}) {
|
|
8672
|
+
const {
|
|
8673
|
+
weekCount = 8,
|
|
8674
|
+
startDate,
|
|
8675
|
+
allowTimelineExtension = true,
|
|
8676
|
+
maxEarlierWeeks = 4,
|
|
8677
|
+
showToolbar = true,
|
|
8678
|
+
showPagination = true,
|
|
8679
|
+
pageSizeOptions = [10, 20, 30],
|
|
8680
|
+
defaultPageSize = 10,
|
|
8681
|
+
stickyRowHeader = true,
|
|
8682
|
+
maxHeight = "500px",
|
|
8683
|
+
onCellChange,
|
|
8684
|
+
onSubmit,
|
|
8685
|
+
onAddComment,
|
|
8686
|
+
onAddEarlierWeek
|
|
8687
|
+
} = config;
|
|
8688
|
+
const calculatedStartDate = React22__namespace.useMemo(() => {
|
|
8689
|
+
if (startDate) return startDate;
|
|
8690
|
+
let earliest = null;
|
|
8691
|
+
for (const prefix of prefixes) {
|
|
8692
|
+
for (const weekKey in prefix.weeks) {
|
|
8693
|
+
const cell = prefix.weeks[weekKey];
|
|
8694
|
+
if (cell.planned > 0) {
|
|
8695
|
+
const match = weekKey.match(/(\d{4})-W(\d{2})/);
|
|
8696
|
+
if (match) {
|
|
8697
|
+
const year = parseInt(match[1]);
|
|
8698
|
+
const week = parseInt(match[2]);
|
|
8699
|
+
const date = new Date(year, 0, 1 + (week - 1) * 7);
|
|
8700
|
+
if (earliest === null || date < earliest) {
|
|
8701
|
+
earliest = date;
|
|
8702
|
+
}
|
|
8703
|
+
}
|
|
8704
|
+
}
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
return earliest ?? /* @__PURE__ */ new Date();
|
|
8708
|
+
}, [startDate, prefixes]);
|
|
8709
|
+
const [additionalWeeks, setAdditionalWeeks] = React22__namespace.useState(0);
|
|
8710
|
+
const weeks = React22__namespace.useMemo(() => {
|
|
8711
|
+
const start = new Date(calculatedStartDate);
|
|
8712
|
+
start.setDate(start.getDate() - additionalWeeks * 7);
|
|
8713
|
+
return generateWeeks(start, weekCount + additionalWeeks);
|
|
8714
|
+
}, [calculatedStartDate, weekCount, additionalWeeks]);
|
|
8715
|
+
React22__namespace.useMemo(() => {
|
|
8716
|
+
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
8717
|
+
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
8718
|
+
}, [weeks]);
|
|
8719
|
+
const [currentPage, setCurrentPage] = React22__namespace.useState(0);
|
|
8720
|
+
const [pageSize, setPageSize] = React22__namespace.useState(defaultPageSize);
|
|
8721
|
+
const [searchQuery, setSearchQuery] = React22__namespace.useState("");
|
|
8722
|
+
const filteredPrefixes = React22__namespace.useMemo(() => {
|
|
8723
|
+
if (!searchQuery) return prefixes;
|
|
8724
|
+
const query = searchQuery.toLowerCase();
|
|
8725
|
+
return prefixes.filter(
|
|
8726
|
+
(p) => p.name.toLowerCase().includes(query) || p.typeCode.toLowerCase().includes(query)
|
|
8727
|
+
);
|
|
8728
|
+
}, [prefixes, searchQuery]);
|
|
8729
|
+
const paginatedPrefixes = React22__namespace.useMemo(() => {
|
|
8730
|
+
const start = currentPage * pageSize;
|
|
8731
|
+
return filteredPrefixes.slice(start, start + pageSize);
|
|
8732
|
+
}, [filteredPrefixes, currentPage, pageSize]);
|
|
8733
|
+
React22__namespace.useMemo(
|
|
8734
|
+
() => canSubmitCalibration(prefixes),
|
|
8735
|
+
[prefixes]
|
|
8736
|
+
);
|
|
8737
|
+
const handleAddEarlierWeek = () => {
|
|
8738
|
+
if (additionalWeeks < maxEarlierWeeks) {
|
|
8739
|
+
setAdditionalWeeks((prev) => prev + 1);
|
|
8740
|
+
onAddEarlierWeek?.();
|
|
8741
|
+
}
|
|
8742
|
+
};
|
|
8743
|
+
const handleCellChange = (prefixId, weekKey, value) => {
|
|
8744
|
+
onCellChange?.(prefixId, weekKey, value);
|
|
8745
|
+
};
|
|
8746
|
+
const handleAddWeekComment = (weekKey, text, prefixId, prefixName) => {
|
|
8747
|
+
onAddComment?.(prefixId, weekKey, text);
|
|
8748
|
+
};
|
|
8749
|
+
const getWeekComments = (weekKey) => {
|
|
8750
|
+
const allComments = [];
|
|
8751
|
+
for (const prefix of prefixes) {
|
|
8752
|
+
const weekComments = prefix.comments?.filter((c) => c.weekKey === weekKey) ?? [];
|
|
8753
|
+
allComments.push(...weekComments);
|
|
8754
|
+
}
|
|
8755
|
+
return allComments;
|
|
8756
|
+
};
|
|
8757
|
+
const availablePrefixes = React22__namespace.useMemo(
|
|
8758
|
+
() => prefixes.map((p) => ({ id: p.id, name: p.name })),
|
|
8759
|
+
[prefixes]
|
|
8760
|
+
);
|
|
8761
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8762
|
+
"div",
|
|
8763
|
+
{
|
|
8764
|
+
"data-slot": "calibration-table",
|
|
8765
|
+
className: cn("flex flex-col gap-4", className),
|
|
8766
|
+
children: [
|
|
8767
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
8768
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: "Weekly Production Calibration" }),
|
|
8769
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "Review required weekly production and confirm achievable output at the selected checkpoint." })
|
|
8770
|
+
] }) }),
|
|
8771
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8772
|
+
showToolbar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
8773
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8774
|
+
Input,
|
|
8775
|
+
{
|
|
8776
|
+
placeholder: "Search prefixes...",
|
|
8777
|
+
value: searchQuery,
|
|
8778
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
8779
|
+
className: "h-8 w-[200px] lg:w-[300px]"
|
|
8780
|
+
}
|
|
8781
|
+
) }),
|
|
8782
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: allowTimelineExtension && additionalWeeks < maxEarlierWeeks && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8783
|
+
Button,
|
|
8784
|
+
{
|
|
8785
|
+
variant: "outline",
|
|
8786
|
+
size: "sm",
|
|
8787
|
+
className: "gap-2",
|
|
8788
|
+
onClick: handleAddEarlierWeek,
|
|
8789
|
+
children: [
|
|
8790
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }),
|
|
8791
|
+
"Add earlier week"
|
|
8792
|
+
]
|
|
8793
|
+
}
|
|
8794
|
+
) })
|
|
8795
|
+
] }),
|
|
8796
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border bg-background shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8797
|
+
ScrollArea,
|
|
8798
|
+
{
|
|
8799
|
+
className: "w-full",
|
|
8800
|
+
style: { maxHeight },
|
|
8801
|
+
children: [
|
|
8802
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
|
|
8803
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "sticky top-0 z-20", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
8804
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: cn(
|
|
8805
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
8806
|
+
"border-r border-b border-border bg-sidebar",
|
|
8807
|
+
stickyRowHeader && "sticky left-0 z-30 min-w-[200px]",
|
|
8808
|
+
// Right shadow using Quantum token
|
|
8809
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
8810
|
+
), children: "Supplier / Scope" }),
|
|
8811
|
+
weeks.map((week) => {
|
|
8812
|
+
const weekKey = getWeekKey(week.startDate);
|
|
8813
|
+
const weekComments = getWeekComments(weekKey);
|
|
8814
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8815
|
+
"th",
|
|
8816
|
+
{
|
|
8817
|
+
className: "h-14 px-2 text-left align-middle border-r border-b border-border last:border-r-0 min-w-[220px] bg-sidebar",
|
|
8818
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8819
|
+
CalibrationWeekHeader,
|
|
8820
|
+
{
|
|
8821
|
+
week,
|
|
8822
|
+
comments: weekComments,
|
|
8823
|
+
showCommentButton: true,
|
|
8824
|
+
availablePrefixes,
|
|
8825
|
+
onAddComment: (text, prefixId, prefixName) => handleAddWeekComment(weekKey, text, prefixId)
|
|
8826
|
+
}
|
|
8827
|
+
)
|
|
8828
|
+
},
|
|
8829
|
+
weekKey
|
|
8830
|
+
);
|
|
8831
|
+
})
|
|
8832
|
+
] }) }),
|
|
8833
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-background", children: paginatedPrefixes.length > 0 ? paginatedPrefixes.map((prefix) => {
|
|
8834
|
+
const sortedWeekKeys = weeks.map((w) => getWeekKey(w.startDate));
|
|
8835
|
+
let hasDeficit = false;
|
|
8836
|
+
const forcedRedMap = {};
|
|
8837
|
+
for (const weekKey of sortedWeekKeys) {
|
|
8838
|
+
const cellData = prefix.weeks[weekKey];
|
|
8839
|
+
if (hasDeficit) {
|
|
8840
|
+
forcedRedMap[weekKey] = true;
|
|
8841
|
+
} else if (cellData && cellData.status === "shortfall") {
|
|
8842
|
+
hasDeficit = true;
|
|
8843
|
+
forcedRedMap[weekKey] = false;
|
|
8844
|
+
} else {
|
|
8845
|
+
forcedRedMap[weekKey] = false;
|
|
8846
|
+
}
|
|
8847
|
+
}
|
|
8848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-border last:border-b-0", children: [
|
|
8849
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8850
|
+
"td",
|
|
8851
|
+
{
|
|
8852
|
+
className: cn(
|
|
8853
|
+
"p-0 align-top border-r border-border bg-background",
|
|
8854
|
+
stickyRowHeader && "sticky left-0 z-10 min-w-[200px]",
|
|
8855
|
+
// Right shadow using Quantum token
|
|
8856
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
8857
|
+
),
|
|
8858
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RowHeaderCell, { data: prefix, showProgress: true })
|
|
8859
|
+
}
|
|
8860
|
+
),
|
|
8861
|
+
weeks.map((week) => {
|
|
8862
|
+
const weekKey = getWeekKey(week.startDate);
|
|
8863
|
+
const cellData = prefix.weeks[weekKey];
|
|
8864
|
+
const isForcedRed = forcedRedMap[weekKey] ?? false;
|
|
8865
|
+
const isEmpty = !cellData || cellData.planned === 0;
|
|
8866
|
+
const effectiveCellData = cellData ?? {
|
|
8867
|
+
planned: 0,
|
|
8868
|
+
entered: null,
|
|
8869
|
+
accumulatedPlanned: 0,
|
|
8870
|
+
accumulatedEntered: 0,
|
|
8871
|
+
net: 0,
|
|
8872
|
+
status: "pending",
|
|
8873
|
+
isEditable: true
|
|
8874
|
+
};
|
|
8875
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8876
|
+
"td",
|
|
8877
|
+
{
|
|
8878
|
+
className: "p-0 align-top border-r border-border last:border-r-0 min-w-[220px] bg-background",
|
|
8879
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8880
|
+
CalibrationWeekCell,
|
|
8881
|
+
{
|
|
8882
|
+
data: effectiveCellData,
|
|
8883
|
+
unit: prefix.unit,
|
|
8884
|
+
onValueChange: (value) => handleCellChange(prefix.id, weekKey, value),
|
|
8885
|
+
forcedRed: isForcedRed,
|
|
8886
|
+
isEmpty,
|
|
8887
|
+
onAddClick: () => {
|
|
8888
|
+
}
|
|
8889
|
+
}
|
|
8890
|
+
)
|
|
8891
|
+
},
|
|
8892
|
+
weekKey
|
|
8893
|
+
);
|
|
8894
|
+
})
|
|
8895
|
+
] }, prefix.id);
|
|
8896
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8897
|
+
"td",
|
|
8898
|
+
{
|
|
8899
|
+
colSpan: weeks.length + 1,
|
|
8900
|
+
className: "h-24 text-center text-muted-foreground bg-background",
|
|
8901
|
+
children: "No prefixes found."
|
|
8902
|
+
}
|
|
8903
|
+
) }) })
|
|
8904
|
+
] }),
|
|
8905
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, { orientation: "horizontal" }),
|
|
8906
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, { orientation: "vertical" })
|
|
8907
|
+
]
|
|
8908
|
+
}
|
|
8909
|
+
) })
|
|
8910
|
+
] }),
|
|
8911
|
+
showPagination && filteredPrefixes.length > pageSize && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-2", children: [
|
|
8912
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
8913
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rows per page" }),
|
|
8914
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8915
|
+
"select",
|
|
8916
|
+
{
|
|
8917
|
+
value: pageSize,
|
|
8918
|
+
onChange: (e) => {
|
|
8919
|
+
setPageSize(Number(e.target.value));
|
|
8920
|
+
setCurrentPage(0);
|
|
8921
|
+
},
|
|
8922
|
+
className: "h-8 w-16 rounded-md border bg-background px-2 text-sm",
|
|
8923
|
+
children: pageSizeOptions.map((size) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: size, children: size }, size))
|
|
8924
|
+
}
|
|
8925
|
+
)
|
|
8926
|
+
] }),
|
|
8927
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
8928
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
8929
|
+
"Page ",
|
|
8930
|
+
currentPage + 1,
|
|
8931
|
+
" of ",
|
|
8932
|
+
Math.ceil(filteredPrefixes.length / pageSize)
|
|
8933
|
+
] }),
|
|
8934
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8935
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8936
|
+
Button,
|
|
8937
|
+
{
|
|
8938
|
+
variant: "outline",
|
|
8939
|
+
size: "icon",
|
|
8940
|
+
className: "h-8 w-8",
|
|
8941
|
+
disabled: currentPage === 0,
|
|
8942
|
+
onClick: () => setCurrentPage(0),
|
|
8943
|
+
children: "\xAB\xAB"
|
|
8944
|
+
}
|
|
8945
|
+
),
|
|
8946
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8947
|
+
Button,
|
|
8948
|
+
{
|
|
8949
|
+
variant: "outline",
|
|
8950
|
+
size: "icon",
|
|
8951
|
+
className: "h-8 w-8",
|
|
8952
|
+
disabled: currentPage === 0,
|
|
8953
|
+
onClick: () => setCurrentPage((prev) => prev - 1),
|
|
8954
|
+
children: "\xAB"
|
|
8955
|
+
}
|
|
8956
|
+
),
|
|
8957
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8958
|
+
Button,
|
|
8959
|
+
{
|
|
8960
|
+
variant: "outline",
|
|
8961
|
+
size: "icon",
|
|
8962
|
+
className: "h-8 w-8",
|
|
8963
|
+
disabled: currentPage >= Math.ceil(filteredPrefixes.length / pageSize) - 1,
|
|
8964
|
+
onClick: () => setCurrentPage((prev) => prev + 1),
|
|
8965
|
+
children: "\xBB"
|
|
8966
|
+
}
|
|
8967
|
+
),
|
|
8968
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8969
|
+
Button,
|
|
8970
|
+
{
|
|
8971
|
+
variant: "outline",
|
|
8972
|
+
size: "icon",
|
|
8973
|
+
className: "h-8 w-8",
|
|
8974
|
+
disabled: currentPage >= Math.ceil(filteredPrefixes.length / pageSize) - 1,
|
|
8975
|
+
onClick: () => setCurrentPage(Math.ceil(filteredPrefixes.length / pageSize) - 1),
|
|
8976
|
+
children: "\xBB\xBB"
|
|
8977
|
+
}
|
|
8978
|
+
)
|
|
8979
|
+
] })
|
|
8980
|
+
] })
|
|
8981
|
+
] })
|
|
8982
|
+
]
|
|
8983
|
+
}
|
|
8984
|
+
);
|
|
8985
|
+
}
|
|
8986
|
+
function CommentDialog({
|
|
8987
|
+
prefixes,
|
|
8988
|
+
weeks,
|
|
8989
|
+
onAddComment,
|
|
8990
|
+
triggerVariant = "outline",
|
|
8991
|
+
open,
|
|
8992
|
+
onOpenChange
|
|
8993
|
+
}) {
|
|
8994
|
+
const [selectedPrefixId, setSelectedPrefixId] = React22__namespace.useState("");
|
|
8995
|
+
const [selectedWeekKey, setSelectedWeekKey] = React22__namespace.useState("");
|
|
8996
|
+
const [commentText, setCommentText] = React22__namespace.useState("");
|
|
8997
|
+
const currentWeek = React22__namespace.useMemo(
|
|
8998
|
+
() => weeks.find((w) => w.isCurrentWeek),
|
|
8999
|
+
[weeks]
|
|
9000
|
+
);
|
|
9001
|
+
React22__namespace.useEffect(() => {
|
|
9002
|
+
if (open) {
|
|
9003
|
+
setSelectedPrefixId(prefixes[0]?.id ?? "");
|
|
9004
|
+
setSelectedWeekKey(currentWeek ? getWeekKey(currentWeek.startDate) : weeks[0] ? getWeekKey(weeks[0].startDate) : "");
|
|
9005
|
+
setCommentText("");
|
|
5712
9006
|
}
|
|
5713
|
-
)
|
|
5714
|
-
)
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
9007
|
+
}, [open, prefixes, weeks, currentWeek]);
|
|
9008
|
+
const handleSave = () => {
|
|
9009
|
+
if (selectedPrefixId && selectedWeekKey && commentText.trim()) {
|
|
9010
|
+
onAddComment?.(selectedPrefixId, selectedWeekKey, commentText.trim());
|
|
9011
|
+
onOpenChange?.(false);
|
|
9012
|
+
}
|
|
9013
|
+
};
|
|
9014
|
+
const isValid = selectedPrefixId && selectedWeekKey && commentText.trim();
|
|
9015
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { open, onOpenChange, children: [
|
|
9016
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: triggerVariant, size: "sm", className: "gap-2", children: [
|
|
9017
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquarePlus, { className: "h-4 w-4" }),
|
|
9018
|
+
"Add comment"
|
|
9019
|
+
] }) }),
|
|
9020
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-[425px]", children: [
|
|
9021
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
9022
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Add Comment" }),
|
|
9023
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Add a comment to a specific prefix and week. Comments help communicate production updates and issues." })
|
|
9024
|
+
] }),
|
|
9025
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 py-4", children: [
|
|
9026
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
|
|
9027
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "prefix-select", children: "Prefix / Element Type" }),
|
|
9028
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedPrefixId, onValueChange: setSelectedPrefixId, children: [
|
|
9029
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: "prefix-select", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select prefix..." }) }),
|
|
9030
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: prefixes.map((prefix) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: prefix.id, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9031
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: prefix.name }),
|
|
9032
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
|
|
9033
|
+
"(",
|
|
9034
|
+
prefix.typeCode,
|
|
9035
|
+
")"
|
|
9036
|
+
] })
|
|
9037
|
+
] }) }, prefix.id)) })
|
|
9038
|
+
] })
|
|
9039
|
+
] }),
|
|
9040
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
|
|
9041
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "week-select", children: "Week" }),
|
|
9042
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedWeekKey, onValueChange: setSelectedWeekKey, children: [
|
|
9043
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: "week-select", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select week..." }) }),
|
|
9044
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: weeks.map((week) => {
|
|
9045
|
+
const weekKey = getWeekKey(week.startDate);
|
|
9046
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: weekKey, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9047
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
9048
|
+
"font-medium",
|
|
9049
|
+
week.isCurrentWeek && "text-primary"
|
|
9050
|
+
), children: week.label }),
|
|
9051
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: week.dateRange }),
|
|
9052
|
+
week.isCurrentWeek && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-primary font-medium", children: "(Current)" })
|
|
9053
|
+
] }) }, weekKey);
|
|
9054
|
+
}) })
|
|
9055
|
+
] })
|
|
9056
|
+
] }),
|
|
9057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
|
|
9058
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: "comment-text", children: "Comment" }),
|
|
9059
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9060
|
+
Textarea,
|
|
9061
|
+
{
|
|
9062
|
+
id: "comment-text",
|
|
9063
|
+
placeholder: "Enter your comment...",
|
|
9064
|
+
value: commentText,
|
|
9065
|
+
onChange: (e) => setCommentText(e.target.value),
|
|
9066
|
+
className: "min-h-[100px] resize-none"
|
|
9067
|
+
}
|
|
9068
|
+
)
|
|
9069
|
+
] })
|
|
9070
|
+
] }),
|
|
9071
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
9072
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => onOpenChange?.(false), children: "Cancel" }),
|
|
9073
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleSave, disabled: !isValid, children: "Save comment" })
|
|
9074
|
+
] })
|
|
9075
|
+
] })
|
|
9076
|
+
] });
|
|
5729
9077
|
}
|
|
5730
|
-
function
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
9078
|
+
function getStatusBadge(status) {
|
|
9079
|
+
switch (status) {
|
|
9080
|
+
case "draft":
|
|
9081
|
+
return { variant: "secondary", label: "DRAFT", color: "bg-blue-500" };
|
|
9082
|
+
case "submitted":
|
|
9083
|
+
return { variant: "secondary", label: "SUBMITTED", color: "bg-amber-500" };
|
|
9084
|
+
case "approved":
|
|
9085
|
+
return { variant: "secondary", label: "APPROVED", color: "bg-green-500" };
|
|
9086
|
+
case "rejected":
|
|
9087
|
+
return { variant: "destructive", label: "REJECTED", color: "bg-red-500" };
|
|
9088
|
+
}
|
|
9089
|
+
}
|
|
9090
|
+
function formatDate(date) {
|
|
9091
|
+
return date.toLocaleDateString("en-US", {
|
|
9092
|
+
month: "short",
|
|
9093
|
+
day: "2-digit",
|
|
9094
|
+
year: "numeric"
|
|
9095
|
+
});
|
|
9096
|
+
}
|
|
9097
|
+
function SubmitCalibrationBar({
|
|
5737
9098
|
className,
|
|
5738
|
-
|
|
9099
|
+
status,
|
|
9100
|
+
lastSaved,
|
|
9101
|
+
canSubmit,
|
|
9102
|
+
shortfallCount,
|
|
9103
|
+
pendingCount,
|
|
9104
|
+
message,
|
|
9105
|
+
onSubmit,
|
|
9106
|
+
onSaveDraft,
|
|
9107
|
+
...props
|
|
5739
9108
|
}) {
|
|
5740
|
-
|
|
5741
|
-
|
|
9109
|
+
const statusBadge = getStatusBadge(status);
|
|
9110
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9111
|
+
"div",
|
|
5742
9112
|
{
|
|
5743
|
-
"data-slot": "
|
|
9113
|
+
"data-slot": "submit-calibration-bar",
|
|
5744
9114
|
className: cn(
|
|
5745
|
-
"
|
|
9115
|
+
"flex items-center justify-between gap-4 px-4 py-4",
|
|
9116
|
+
"bg-background",
|
|
5746
9117
|
className
|
|
5747
9118
|
),
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
function NavMain({ items, label = "Platform" }) {
|
|
5762
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(SidebarGroup, { children: [
|
|
5763
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarGroupLabel, { children: label }),
|
|
5764
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { asChild: true, defaultOpen: item.isActive, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuItem, { children: [
|
|
5765
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, tooltip: item.title, children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
5766
|
-
item.icon && /* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
5767
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title })
|
|
5768
|
-
] }) }),
|
|
5769
|
-
item.items?.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5770
|
-
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuAction, { className: "data-[state=open]:rotate-90", children: [
|
|
5771
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {}),
|
|
5772
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Toggle" })
|
|
5773
|
-
] }) }),
|
|
5774
|
-
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuSubButton, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: subItem.url, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: subItem.title }) }) }) }, subItem.title)) }) })
|
|
5775
|
-
] }) : null
|
|
5776
|
-
] }) }, item.title)) })
|
|
5777
|
-
] });
|
|
5778
|
-
}
|
|
5779
|
-
function NavProjects({ projects, label = "Projects" }) {
|
|
5780
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(SidebarGroup, { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
5781
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarGroupLabel, { children: label }),
|
|
5782
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SidebarMenu, { children: [
|
|
5783
|
-
projects.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuItem, { children: [
|
|
5784
|
-
/* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
5785
|
-
/* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
5786
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.name })
|
|
5787
|
-
] }) }),
|
|
5788
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
5789
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(SidebarMenuAction, { showOnHover: true, children: [
|
|
5790
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontalIcon, {}),
|
|
5791
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "More" })
|
|
5792
|
-
] }) }),
|
|
9119
|
+
...props,
|
|
9120
|
+
children: [
|
|
9121
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9122
|
+
!canSubmit && (shortfallCount > 0 || pendingCount > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
9123
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-4 w-4 text-amber-500" }),
|
|
9124
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: message })
|
|
9125
|
+
] }),
|
|
9126
|
+
canSubmit && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
9127
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-4 w-4 text-green-500" }),
|
|
9128
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: message })
|
|
9129
|
+
] })
|
|
9130
|
+
] }),
|
|
9131
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
5793
9132
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5794
|
-
|
|
9133
|
+
Badge,
|
|
5795
9134
|
{
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
align: "start",
|
|
5799
|
-
sideOffset: 8,
|
|
9135
|
+
variant: statusBadge.variant,
|
|
9136
|
+
className: "flex items-center gap-2 px-3 py-1 rounded-full",
|
|
5800
9137
|
children: [
|
|
5801
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
9138
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("h-2 w-2 rounded-full", statusBadge.color) }),
|
|
9139
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: statusBadge.label })
|
|
9140
|
+
]
|
|
9141
|
+
}
|
|
9142
|
+
),
|
|
9143
|
+
lastSaved && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9144
|
+
Button,
|
|
9145
|
+
{
|
|
9146
|
+
variant: "outline",
|
|
9147
|
+
size: "sm",
|
|
9148
|
+
className: "gap-2 rounded-full",
|
|
9149
|
+
disabled: true,
|
|
9150
|
+
children: [
|
|
9151
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-4 w-4" }),
|
|
9152
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatDate(lastSaved) })
|
|
5814
9153
|
]
|
|
5815
9154
|
}
|
|
9155
|
+
),
|
|
9156
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9157
|
+
Button,
|
|
9158
|
+
{
|
|
9159
|
+
size: "sm",
|
|
9160
|
+
className: "rounded-full px-4 min-w-[140px]",
|
|
9161
|
+
disabled: !canSubmit || status === "submitted" || status === "approved",
|
|
9162
|
+
onClick: onSubmit,
|
|
9163
|
+
children: status === "submitted" ? "Submitted" : status === "approved" ? "Approved" : "Submit calibration"
|
|
9164
|
+
}
|
|
5816
9165
|
)
|
|
5817
9166
|
] })
|
|
5818
|
-
]
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "More" })
|
|
5822
|
-
] }) })
|
|
5823
|
-
] })
|
|
5824
|
-
] });
|
|
5825
|
-
}
|
|
5826
|
-
function NavSecondary({ items, ...props }) {
|
|
5827
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SidebarGroup, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuButton, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: item.url, children: [
|
|
5828
|
-
/* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
|
|
5829
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title })
|
|
5830
|
-
] }) }) }, item.title)) }) }) });
|
|
5831
|
-
}
|
|
5832
|
-
function NavUser({ user }) {
|
|
5833
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
5834
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5835
|
-
SidebarMenuButton,
|
|
5836
|
-
{
|
|
5837
|
-
size: "lg",
|
|
5838
|
-
className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
5839
|
-
children: [
|
|
5840
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5841
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5842
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5843
|
-
] }),
|
|
5844
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5845
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5846
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5847
|
-
] }),
|
|
5848
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDownIcon, { className: "ml-auto size-4" })
|
|
5849
|
-
]
|
|
5850
|
-
}
|
|
5851
|
-
) }),
|
|
5852
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5853
|
-
DropdownMenuContent,
|
|
5854
|
-
{
|
|
5855
|
-
className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-[var(--j3m-radius-m)]",
|
|
5856
|
-
side: "right",
|
|
5857
|
-
align: "end",
|
|
5858
|
-
sideOffset: 8,
|
|
5859
|
-
children: [
|
|
5860
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
|
|
5861
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5862
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5863
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5864
|
-
] }),
|
|
5865
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5866
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5867
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5868
|
-
] })
|
|
5869
|
-
] }) }),
|
|
5870
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
5871
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
5872
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.SparklesIcon, {}),
|
|
5873
|
-
"Upgrade to Pro"
|
|
5874
|
-
] }) }),
|
|
5875
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
5876
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuGroup, { children: [
|
|
5877
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
5878
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BadgeCheckIcon, {}),
|
|
5879
|
-
"Account"
|
|
5880
|
-
] }),
|
|
5881
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
5882
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCardIcon, {}),
|
|
5883
|
-
"Billing"
|
|
5884
|
-
] }),
|
|
5885
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
5886
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BellIcon, {}),
|
|
5887
|
-
"Notifications"
|
|
5888
|
-
] })
|
|
5889
|
-
] }),
|
|
5890
|
-
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
5891
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { children: [
|
|
5892
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOutIcon, {}),
|
|
5893
|
-
"Log out"
|
|
5894
|
-
] })
|
|
5895
|
-
]
|
|
5896
|
-
}
|
|
5897
|
-
)
|
|
5898
|
-
] }) }) });
|
|
9167
|
+
]
|
|
9168
|
+
}
|
|
9169
|
+
);
|
|
5899
9170
|
}
|
|
5900
9171
|
|
|
5901
9172
|
// src/components/event-calendar/types.ts
|
|
@@ -5960,7 +9231,7 @@ var BADGE_VARIANT_LABELS = {
|
|
|
5960
9231
|
colored: "Colored",
|
|
5961
9232
|
mixed: "Mixed"
|
|
5962
9233
|
};
|
|
5963
|
-
var CalendarContext =
|
|
9234
|
+
var CalendarContext = React22__namespace.createContext(null);
|
|
5964
9235
|
function EventCalendarProvider({
|
|
5965
9236
|
children,
|
|
5966
9237
|
events: initialEvents = [],
|
|
@@ -5975,38 +9246,38 @@ function EventCalendarProvider({
|
|
|
5975
9246
|
onEventUpdate,
|
|
5976
9247
|
onEventDelete
|
|
5977
9248
|
}) {
|
|
5978
|
-
const [selectedDate, setSelectedDate] =
|
|
5979
|
-
const [selectedUserId, setSelectedUserId] =
|
|
5980
|
-
const [events, setEventsState] =
|
|
5981
|
-
const [users] =
|
|
5982
|
-
const [badgeVariant, setBadgeVariant] =
|
|
5983
|
-
const [view, setView] =
|
|
5984
|
-
const [workingHours, setWorkingHours] =
|
|
5985
|
-
const [visibleHours, setVisibleHours] =
|
|
5986
|
-
|
|
9249
|
+
const [selectedDate, setSelectedDate] = React22__namespace.useState(defaultDate);
|
|
9250
|
+
const [selectedUserId, setSelectedUserId] = React22__namespace.useState(defaultUserId);
|
|
9251
|
+
const [events, setEventsState] = React22__namespace.useState(initialEvents);
|
|
9252
|
+
const [users] = React22__namespace.useState(initialUsers);
|
|
9253
|
+
const [badgeVariant, setBadgeVariant] = React22__namespace.useState(defaultBadgeVariant);
|
|
9254
|
+
const [view, setView] = React22__namespace.useState(defaultView);
|
|
9255
|
+
const [workingHours, setWorkingHours] = React22__namespace.useState(defaultWorkingHours);
|
|
9256
|
+
const [visibleHours, setVisibleHours] = React22__namespace.useState(defaultVisibleHours);
|
|
9257
|
+
React22__namespace.useEffect(() => {
|
|
5987
9258
|
setEventsState(initialEvents);
|
|
5988
9259
|
}, [initialEvents]);
|
|
5989
|
-
const setEvents =
|
|
9260
|
+
const setEvents = React22__namespace.useCallback((newEvents) => {
|
|
5990
9261
|
setEventsState(newEvents);
|
|
5991
9262
|
}, []);
|
|
5992
|
-
const addEvent =
|
|
9263
|
+
const addEvent = React22__namespace.useCallback((event) => {
|
|
5993
9264
|
setEventsState((prev) => [...prev, event]);
|
|
5994
9265
|
onEventAdd?.(event);
|
|
5995
9266
|
}, [onEventAdd]);
|
|
5996
|
-
const updateEvent =
|
|
9267
|
+
const updateEvent = React22__namespace.useCallback((event) => {
|
|
5997
9268
|
setEventsState(
|
|
5998
9269
|
(prev) => prev.map((e) => e.id === event.id ? event : e)
|
|
5999
9270
|
);
|
|
6000
9271
|
onEventUpdate?.(event);
|
|
6001
9272
|
}, [onEventUpdate]);
|
|
6002
|
-
const deleteEvent =
|
|
9273
|
+
const deleteEvent = React22__namespace.useCallback((eventId) => {
|
|
6003
9274
|
setEventsState((prev) => prev.filter((e) => e.id !== eventId));
|
|
6004
9275
|
onEventDelete?.(eventId);
|
|
6005
9276
|
}, [onEventDelete]);
|
|
6006
|
-
const goToToday =
|
|
9277
|
+
const goToToday = React22__namespace.useCallback(() => {
|
|
6007
9278
|
setSelectedDate(/* @__PURE__ */ new Date());
|
|
6008
9279
|
}, []);
|
|
6009
|
-
const goToPrevious =
|
|
9280
|
+
const goToPrevious = React22__namespace.useCallback(() => {
|
|
6010
9281
|
setSelectedDate((current) => {
|
|
6011
9282
|
switch (view) {
|
|
6012
9283
|
case "day":
|
|
@@ -6024,7 +9295,7 @@ function EventCalendarProvider({
|
|
|
6024
9295
|
}
|
|
6025
9296
|
});
|
|
6026
9297
|
}, [view]);
|
|
6027
|
-
const goToNext =
|
|
9298
|
+
const goToNext = React22__namespace.useCallback(() => {
|
|
6028
9299
|
setSelectedDate((current) => {
|
|
6029
9300
|
switch (view) {
|
|
6030
9301
|
case "day":
|
|
@@ -6042,7 +9313,7 @@ function EventCalendarProvider({
|
|
|
6042
9313
|
}
|
|
6043
9314
|
});
|
|
6044
9315
|
}, [view]);
|
|
6045
|
-
const contextValue =
|
|
9316
|
+
const contextValue = React22__namespace.useMemo(
|
|
6046
9317
|
() => ({
|
|
6047
9318
|
// State
|
|
6048
9319
|
selectedDate,
|
|
@@ -6089,7 +9360,7 @@ function EventCalendarProvider({
|
|
|
6089
9360
|
return /* @__PURE__ */ jsxRuntime.jsx(CalendarContext.Provider, { value: contextValue, children });
|
|
6090
9361
|
}
|
|
6091
9362
|
function useEventCalendar() {
|
|
6092
|
-
const context =
|
|
9363
|
+
const context = React22__namespace.useContext(CalendarContext);
|
|
6093
9364
|
if (!context) {
|
|
6094
9365
|
throw new Error("useEventCalendar must be used within an EventCalendarProvider");
|
|
6095
9366
|
}
|
|
@@ -6097,14 +9368,14 @@ function useEventCalendar() {
|
|
|
6097
9368
|
}
|
|
6098
9369
|
function useFilteredEvents() {
|
|
6099
9370
|
const { events, selectedUserId } = useEventCalendar();
|
|
6100
|
-
return
|
|
9371
|
+
return React22__namespace.useMemo(() => {
|
|
6101
9372
|
if (!selectedUserId) return events;
|
|
6102
9373
|
return events.filter((event) => event.user.id === selectedUserId);
|
|
6103
9374
|
}, [events, selectedUserId]);
|
|
6104
9375
|
}
|
|
6105
9376
|
function useEventsInRange(startDate, endDate) {
|
|
6106
9377
|
const filteredEvents = useFilteredEvents();
|
|
6107
|
-
return
|
|
9378
|
+
return React22__namespace.useMemo(() => {
|
|
6108
9379
|
return filteredEvents.filter((event) => {
|
|
6109
9380
|
const eventStart = new Date(event.startDate);
|
|
6110
9381
|
const eventEnd = new Date(event.endDate);
|
|
@@ -6478,7 +9749,7 @@ function getViewDateRange(date, view) {
|
|
|
6478
9749
|
return { start: dateFns.startOfMonth(date), end: dateFns.endOfMonth(date) };
|
|
6479
9750
|
}
|
|
6480
9751
|
}
|
|
6481
|
-
function
|
|
9752
|
+
function formatDateRange2(start, end) {
|
|
6482
9753
|
if (dateFns.isSameDay(start, end)) {
|
|
6483
9754
|
return dateFns.format(start, "MMM d, yyyy");
|
|
6484
9755
|
}
|
|
@@ -6662,8 +9933,8 @@ function MoreEvents({ count, onClick, className }) {
|
|
|
6662
9933
|
);
|
|
6663
9934
|
}
|
|
6664
9935
|
function TimeIndicator({ className }) {
|
|
6665
|
-
const [now, setNow] =
|
|
6666
|
-
|
|
9936
|
+
const [now, setNow] = React22__namespace.useState(/* @__PURE__ */ new Date());
|
|
9937
|
+
React22__namespace.useEffect(() => {
|
|
6667
9938
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
6668
9939
|
return () => clearInterval(interval);
|
|
6669
9940
|
}, []);
|
|
@@ -6700,24 +9971,24 @@ function DateBadge({ date, className }) {
|
|
|
6700
9971
|
}
|
|
6701
9972
|
);
|
|
6702
9973
|
}
|
|
6703
|
-
var DragContext =
|
|
9974
|
+
var DragContext = React22__namespace.createContext(null);
|
|
6704
9975
|
function DragProvider({
|
|
6705
9976
|
children,
|
|
6706
9977
|
snapMinutes = 15,
|
|
6707
9978
|
onDragStart,
|
|
6708
9979
|
onDragEnd
|
|
6709
9980
|
}) {
|
|
6710
|
-
const [draggedEvent, setDraggedEventState] =
|
|
6711
|
-
const [isDragging, setIsDragging] =
|
|
9981
|
+
const [draggedEvent, setDraggedEventState] = React22__namespace.useState(null);
|
|
9982
|
+
const [isDragging, setIsDragging] = React22__namespace.useState(false);
|
|
6712
9983
|
const { updateEvent } = useEventCalendar();
|
|
6713
|
-
const setDraggedEvent =
|
|
9984
|
+
const setDraggedEvent = React22__namespace.useCallback((event) => {
|
|
6714
9985
|
setDraggedEventState(event);
|
|
6715
9986
|
setIsDragging(!!event);
|
|
6716
9987
|
if (event) {
|
|
6717
9988
|
onDragStart?.(event);
|
|
6718
9989
|
}
|
|
6719
9990
|
}, [onDragStart]);
|
|
6720
|
-
const handleDrop =
|
|
9991
|
+
const handleDrop = React22__namespace.useCallback((newStartDate) => {
|
|
6721
9992
|
if (!draggedEvent) return;
|
|
6722
9993
|
const snappedDate = snapToInterval(newStartDate, snapMinutes);
|
|
6723
9994
|
const { startDate, endDate } = calculateDropDates(draggedEvent, snappedDate);
|
|
@@ -6730,7 +10001,7 @@ function DragProvider({
|
|
|
6730
10001
|
onDragEnd?.(updatedEvent, new Date(startDate), new Date(endDate));
|
|
6731
10002
|
setDraggedEvent(null);
|
|
6732
10003
|
}, [draggedEvent, snapMinutes, updateEvent, onDragEnd, setDraggedEvent]);
|
|
6733
|
-
const contextValue =
|
|
10004
|
+
const contextValue = React22__namespace.useMemo(
|
|
6734
10005
|
() => ({
|
|
6735
10006
|
draggedEvent,
|
|
6736
10007
|
setDraggedEvent,
|
|
@@ -6741,7 +10012,7 @@ function DragProvider({
|
|
|
6741
10012
|
return /* @__PURE__ */ jsxRuntime.jsx(DragContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(DragDropHandler, { onDrop: handleDrop, children }) });
|
|
6742
10013
|
}
|
|
6743
10014
|
function useDrag() {
|
|
6744
|
-
const context =
|
|
10015
|
+
const context = React22__namespace.useContext(DragContext);
|
|
6745
10016
|
if (!context) {
|
|
6746
10017
|
throw new Error("useDrag must be used within a DragProvider");
|
|
6747
10018
|
}
|
|
@@ -6786,7 +10057,7 @@ function DroppableZone({
|
|
|
6786
10057
|
}) {
|
|
6787
10058
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6788
10059
|
const { updateEvent } = useEventCalendar();
|
|
6789
|
-
const [isOver, setIsOver] =
|
|
10060
|
+
const [isOver, setIsOver] = React22__namespace.useState(false);
|
|
6790
10061
|
const handleDragOver = (e) => {
|
|
6791
10062
|
e.preventDefault();
|
|
6792
10063
|
e.dataTransfer.dropEffect = "move";
|
|
@@ -6824,23 +10095,23 @@ function DroppableZone({
|
|
|
6824
10095
|
function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
6825
10096
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6826
10097
|
const { updateEvent } = useEventCalendar();
|
|
6827
|
-
const [isOver, setIsOver] =
|
|
6828
|
-
const dropTargetDate =
|
|
10098
|
+
const [isOver, setIsOver] = React22__namespace.useState(false);
|
|
10099
|
+
const dropTargetDate = React22__namespace.useMemo(() => {
|
|
6829
10100
|
const targetDate = new Date(date);
|
|
6830
10101
|
if (hour !== void 0) {
|
|
6831
10102
|
targetDate.setHours(hour, minute, 0, 0);
|
|
6832
10103
|
}
|
|
6833
10104
|
return targetDate;
|
|
6834
10105
|
}, [date, hour, minute]);
|
|
6835
|
-
const handleDragOver =
|
|
10106
|
+
const handleDragOver = React22__namespace.useCallback((e) => {
|
|
6836
10107
|
e.preventDefault();
|
|
6837
10108
|
e.dataTransfer.dropEffect = "move";
|
|
6838
10109
|
if (!isOver) setIsOver(true);
|
|
6839
10110
|
}, [isOver]);
|
|
6840
|
-
const handleDragLeave =
|
|
10111
|
+
const handleDragLeave = React22__namespace.useCallback(() => {
|
|
6841
10112
|
setIsOver(false);
|
|
6842
10113
|
}, []);
|
|
6843
|
-
const handleDrop =
|
|
10114
|
+
const handleDrop = React22__namespace.useCallback((e) => {
|
|
6844
10115
|
e.preventDefault();
|
|
6845
10116
|
setIsOver(false);
|
|
6846
10117
|
if (!draggedEvent) return;
|
|
@@ -6867,13 +10138,13 @@ function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
|
6867
10138
|
function useDraggable(event, disabled = false) {
|
|
6868
10139
|
const { setDraggedEvent, draggedEvent } = useDrag();
|
|
6869
10140
|
const isDragged = draggedEvent?.id === event.id;
|
|
6870
|
-
const handleDragStart =
|
|
10141
|
+
const handleDragStart = React22__namespace.useCallback((e) => {
|
|
6871
10142
|
if (disabled) return;
|
|
6872
10143
|
e.dataTransfer.effectAllowed = "move";
|
|
6873
10144
|
e.dataTransfer.setData("text/plain", event.id);
|
|
6874
10145
|
setDraggedEvent(event);
|
|
6875
10146
|
}, [disabled, event, setDraggedEvent]);
|
|
6876
|
-
const handleDragEnd =
|
|
10147
|
+
const handleDragEnd = React22__namespace.useCallback(() => {
|
|
6877
10148
|
setDraggedEvent(null);
|
|
6878
10149
|
}, [setDraggedEvent]);
|
|
6879
10150
|
return {
|
|
@@ -6914,15 +10185,15 @@ function MonthView({
|
|
|
6914
10185
|
}) {
|
|
6915
10186
|
const { selectedDate, badgeVariant, setSelectedDate, setView } = useEventCalendar();
|
|
6916
10187
|
const filteredEvents = useFilteredEvents();
|
|
6917
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10188
|
+
const { singleDayEvents, multiDayEvents } = React22__namespace.useMemo(
|
|
6918
10189
|
() => splitEventsByDuration(filteredEvents),
|
|
6919
10190
|
[filteredEvents]
|
|
6920
10191
|
);
|
|
6921
|
-
const cells =
|
|
10192
|
+
const cells = React22__namespace.useMemo(
|
|
6922
10193
|
() => getCalendarCells(selectedDate),
|
|
6923
10194
|
[selectedDate]
|
|
6924
10195
|
);
|
|
6925
|
-
const eventPositions =
|
|
10196
|
+
const eventPositions = React22__namespace.useMemo(
|
|
6926
10197
|
() => calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate),
|
|
6927
10198
|
[multiDayEvents, singleDayEvents, selectedDate]
|
|
6928
10199
|
);
|
|
@@ -7104,7 +10375,7 @@ function WeekView({
|
|
|
7104
10375
|
visibleHours
|
|
7105
10376
|
} = useEventCalendar();
|
|
7106
10377
|
const filteredEvents = useFilteredEvents();
|
|
7107
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10378
|
+
const { singleDayEvents, multiDayEvents } = React22__namespace.useMemo(
|
|
7108
10379
|
() => splitEventsByDuration(filteredEvents),
|
|
7109
10380
|
[filteredEvents]
|
|
7110
10381
|
);
|
|
@@ -7310,8 +10581,8 @@ function CalendarTimeline({
|
|
|
7310
10581
|
firstVisibleHour,
|
|
7311
10582
|
lastVisibleHour
|
|
7312
10583
|
}) {
|
|
7313
|
-
const [currentTime, setCurrentTime] =
|
|
7314
|
-
|
|
10584
|
+
const [currentTime, setCurrentTime] = React22__namespace.useState(/* @__PURE__ */ new Date());
|
|
10585
|
+
React22__namespace.useEffect(() => {
|
|
7315
10586
|
const interval = setInterval(() => {
|
|
7316
10587
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7317
10588
|
}, 6e4);
|
|
@@ -7394,7 +10665,7 @@ function DayView({
|
|
|
7394
10665
|
visibleHours
|
|
7395
10666
|
} = useEventCalendar();
|
|
7396
10667
|
const filteredEvents = useFilteredEvents();
|
|
7397
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10668
|
+
const { singleDayEvents, multiDayEvents } = React22__namespace.useMemo(
|
|
7398
10669
|
() => splitEventsByDuration(filteredEvents),
|
|
7399
10670
|
[filteredEvents]
|
|
7400
10671
|
);
|
|
@@ -7402,7 +10673,7 @@ function DayView({
|
|
|
7402
10673
|
visibleHours,
|
|
7403
10674
|
singleDayEvents
|
|
7404
10675
|
);
|
|
7405
|
-
const currentEvents =
|
|
10676
|
+
const currentEvents = React22__namespace.useMemo(() => {
|
|
7406
10677
|
if (!dateFns.isToday(selectedDate)) return [];
|
|
7407
10678
|
return getCurrentEvents(singleDayEvents);
|
|
7408
10679
|
}, [singleDayEvents, selectedDate]);
|
|
@@ -7626,8 +10897,8 @@ function CalendarTimeline2({
|
|
|
7626
10897
|
firstVisibleHour,
|
|
7627
10898
|
lastVisibleHour
|
|
7628
10899
|
}) {
|
|
7629
|
-
const [currentTime, setCurrentTime] =
|
|
7630
|
-
|
|
10900
|
+
const [currentTime, setCurrentTime] = React22__namespace.useState(/* @__PURE__ */ new Date());
|
|
10901
|
+
React22__namespace.useEffect(() => {
|
|
7631
10902
|
const interval = setInterval(() => {
|
|
7632
10903
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7633
10904
|
}, 6e4);
|
|
@@ -7661,7 +10932,7 @@ function YearView({
|
|
|
7661
10932
|
}) {
|
|
7662
10933
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7663
10934
|
const filteredEvents = useFilteredEvents();
|
|
7664
|
-
const months =
|
|
10935
|
+
const months = React22__namespace.useMemo(() => {
|
|
7665
10936
|
const yearStart = dateFns.startOfYear(selectedDate);
|
|
7666
10937
|
return Array.from({ length: 12 }, (_, i) => dateFns.addMonths(yearStart, i));
|
|
7667
10938
|
}, [selectedDate]);
|
|
@@ -7784,11 +11055,11 @@ function AgendaView({
|
|
|
7784
11055
|
}) {
|
|
7785
11056
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7786
11057
|
const filteredEvents = useFilteredEvents();
|
|
7787
|
-
const { singleDayEvents, multiDayEvents } =
|
|
11058
|
+
const { singleDayEvents, multiDayEvents } = React22__namespace.useMemo(
|
|
7788
11059
|
() => splitEventsByDuration(filteredEvents),
|
|
7789
11060
|
[filteredEvents]
|
|
7790
11061
|
);
|
|
7791
|
-
const eventsByDay =
|
|
11062
|
+
const eventsByDay = React22__namespace.useMemo(() => {
|
|
7792
11063
|
const allDates = /* @__PURE__ */ new Map();
|
|
7793
11064
|
singleDayEvents.forEach((event) => {
|
|
7794
11065
|
const eventDate = dateFns.parseISO(event.startDate);
|
|
@@ -7981,7 +11252,7 @@ function CalendarHeader({
|
|
|
7981
11252
|
const filteredEvents = useFilteredEvents();
|
|
7982
11253
|
const eventCount = filteredEvents.length;
|
|
7983
11254
|
const { start: rangeStart, end: rangeEnd } = getViewDateRange(selectedDate, view);
|
|
7984
|
-
const dateRangeLabel =
|
|
11255
|
+
const dateRangeLabel = formatDateRange2(rangeStart, rangeEnd);
|
|
7985
11256
|
const getInitials = (name) => {
|
|
7986
11257
|
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7987
11258
|
};
|
|
@@ -8253,16 +11524,16 @@ function EventDialog({
|
|
|
8253
11524
|
defaultUserId
|
|
8254
11525
|
}) {
|
|
8255
11526
|
const { addEvent, updateEvent, deleteEvent, users } = useEventCalendar();
|
|
8256
|
-
const [title, setTitle] =
|
|
8257
|
-
const [description, setDescription] =
|
|
8258
|
-
const [startDate, setStartDate] =
|
|
8259
|
-
const [startTime, setStartTime] =
|
|
8260
|
-
const [endDate, setEndDate] =
|
|
8261
|
-
const [endTime, setEndTime] =
|
|
8262
|
-
const [color, setColor] =
|
|
8263
|
-
const [userId, setUserId] =
|
|
8264
|
-
const [isSubmitting, setIsSubmitting] =
|
|
8265
|
-
|
|
11527
|
+
const [title, setTitle] = React22__namespace.useState("");
|
|
11528
|
+
const [description, setDescription] = React22__namespace.useState("");
|
|
11529
|
+
const [startDate, setStartDate] = React22__namespace.useState("");
|
|
11530
|
+
const [startTime, setStartTime] = React22__namespace.useState("");
|
|
11531
|
+
const [endDate, setEndDate] = React22__namespace.useState("");
|
|
11532
|
+
const [endTime, setEndTime] = React22__namespace.useState("");
|
|
11533
|
+
const [color, setColor] = React22__namespace.useState("blue");
|
|
11534
|
+
const [userId, setUserId] = React22__namespace.useState("");
|
|
11535
|
+
const [isSubmitting, setIsSubmitting] = React22__namespace.useState(false);
|
|
11536
|
+
React22__namespace.useEffect(() => {
|
|
8266
11537
|
if (open) {
|
|
8267
11538
|
if (mode === "edit" && event) {
|
|
8268
11539
|
const start = dateFns.parseISO(event.startDate);
|
|
@@ -8485,7 +11756,7 @@ function QuickAddEvent({
|
|
|
8485
11756
|
onOpenDialog,
|
|
8486
11757
|
onClose
|
|
8487
11758
|
}) {
|
|
8488
|
-
const [title, setTitle] =
|
|
11759
|
+
const [title, setTitle] = React22__namespace.useState("");
|
|
8489
11760
|
const { users } = useEventCalendar();
|
|
8490
11761
|
const handleSubmit = (e) => {
|
|
8491
11762
|
e.preventDefault();
|
|
@@ -8552,8 +11823,8 @@ var HOUR_OPTIONS = Array.from({ length: 25 }, (_, i) => {
|
|
|
8552
11823
|
});
|
|
8553
11824
|
function ChangeVisibleHoursInput() {
|
|
8554
11825
|
const { visibleHours, setVisibleHours } = useEventCalendar();
|
|
8555
|
-
const [from, setFrom] =
|
|
8556
|
-
const [to, setTo] =
|
|
11826
|
+
const [from, setFrom] = React22__namespace.useState(visibleHours.from);
|
|
11827
|
+
const [to, setTo] = React22__namespace.useState(visibleHours.to);
|
|
8557
11828
|
const handleApply = () => {
|
|
8558
11829
|
const toHour = to === 0 ? 24 : to;
|
|
8559
11830
|
setVisibleHours({ from, to: toHour });
|
|
@@ -8599,7 +11870,7 @@ var HOUR_OPTIONS2 = Array.from({ length: 25 }, (_, i) => {
|
|
|
8599
11870
|
});
|
|
8600
11871
|
function ChangeWorkingHoursInput() {
|
|
8601
11872
|
const { workingHours, setWorkingHours } = useEventCalendar();
|
|
8602
|
-
const [localWorkingHours, setLocalWorkingHours] =
|
|
11873
|
+
const [localWorkingHours, setLocalWorkingHours] = React22__namespace.useState({
|
|
8603
11874
|
...workingHours
|
|
8604
11875
|
});
|
|
8605
11876
|
const handleToggleDay = (dayId) => {
|
|
@@ -8748,8 +12019,8 @@ function CalendarSettingsButton({
|
|
|
8748
12019
|
);
|
|
8749
12020
|
}
|
|
8750
12021
|
function useMediaQuery(query) {
|
|
8751
|
-
const [matches, setMatches] =
|
|
8752
|
-
|
|
12022
|
+
const [matches, setMatches] = React22__namespace.useState(false);
|
|
12023
|
+
React22__namespace.useEffect(() => {
|
|
8753
12024
|
const media = window.matchMedia(query);
|
|
8754
12025
|
setMatches(media.matches);
|
|
8755
12026
|
const listener = (event) => {
|
|
@@ -8801,11 +12072,11 @@ function BigCalendarInner({
|
|
|
8801
12072
|
maxEventsPerDay
|
|
8802
12073
|
}) {
|
|
8803
12074
|
const { view, setView } = useEventCalendar();
|
|
8804
|
-
const [dialogOpen, setDialogOpen] =
|
|
8805
|
-
const [settingsDialogOpen, setSettingsDialogOpen] =
|
|
8806
|
-
const [selectedEvent, setSelectedEvent] =
|
|
8807
|
-
const [dialogMode, setDialogMode] =
|
|
8808
|
-
const [defaultDate, setDefaultDate] =
|
|
12075
|
+
const [dialogOpen, setDialogOpen] = React22__namespace.useState(false);
|
|
12076
|
+
const [settingsDialogOpen, setSettingsDialogOpen] = React22__namespace.useState(false);
|
|
12077
|
+
const [selectedEvent, setSelectedEvent] = React22__namespace.useState(null);
|
|
12078
|
+
const [dialogMode, setDialogMode] = React22__namespace.useState("add");
|
|
12079
|
+
const [defaultDate, setDefaultDate] = React22__namespace.useState(/* @__PURE__ */ new Date());
|
|
8809
12080
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
8810
12081
|
const isCompact = compact === "auto" ? isMobile : compact;
|
|
8811
12082
|
const handleAddClick = () => {
|
|
@@ -8964,6 +12235,30 @@ function CalendarView({
|
|
|
8964
12235
|
}
|
|
8965
12236
|
}
|
|
8966
12237
|
|
|
12238
|
+
Object.defineProperty(exports, "flexRender", {
|
|
12239
|
+
enumerable: true,
|
|
12240
|
+
get: function () { return reactTable.flexRender; }
|
|
12241
|
+
});
|
|
12242
|
+
Object.defineProperty(exports, "getCoreRowModel", {
|
|
12243
|
+
enumerable: true,
|
|
12244
|
+
get: function () { return reactTable.getCoreRowModel; }
|
|
12245
|
+
});
|
|
12246
|
+
Object.defineProperty(exports, "getFilteredRowModel", {
|
|
12247
|
+
enumerable: true,
|
|
12248
|
+
get: function () { return reactTable.getFilteredRowModel; }
|
|
12249
|
+
});
|
|
12250
|
+
Object.defineProperty(exports, "getPaginationRowModel", {
|
|
12251
|
+
enumerable: true,
|
|
12252
|
+
get: function () { return reactTable.getPaginationRowModel; }
|
|
12253
|
+
});
|
|
12254
|
+
Object.defineProperty(exports, "getSortedRowModel", {
|
|
12255
|
+
enumerable: true,
|
|
12256
|
+
get: function () { return reactTable.getSortedRowModel; }
|
|
12257
|
+
});
|
|
12258
|
+
Object.defineProperty(exports, "useReactTable", {
|
|
12259
|
+
enumerable: true,
|
|
12260
|
+
get: function () { return reactTable.useReactTable; }
|
|
12261
|
+
});
|
|
8967
12262
|
Object.defineProperty(exports, "areIntervalsOverlapping", {
|
|
8968
12263
|
enumerable: true,
|
|
8969
12264
|
get: function () { return dateFns.areIntervalsOverlapping; }
|
|
@@ -9037,6 +12332,9 @@ exports.CalendarHeaderCompact = CalendarHeaderCompact;
|
|
|
9037
12332
|
exports.CalendarSettingsButton = CalendarSettingsButton;
|
|
9038
12333
|
exports.CalendarSettingsContent = CalendarSettingsContent;
|
|
9039
12334
|
exports.CalendarSettingsDialog = CalendarSettingsDialog;
|
|
12335
|
+
exports.CalibrationTable = CalibrationTable;
|
|
12336
|
+
exports.CalibrationWeekCell = CalibrationWeekCell;
|
|
12337
|
+
exports.CalibrationWeekHeader = CalibrationWeekHeader;
|
|
9040
12338
|
exports.Card = Card;
|
|
9041
12339
|
exports.CardContent = CardContent;
|
|
9042
12340
|
exports.CardDescription = CardDescription;
|
|
@@ -9058,6 +12356,7 @@ exports.ChartStyle = ChartStyle;
|
|
|
9058
12356
|
exports.ChartTooltip = ChartTooltip;
|
|
9059
12357
|
exports.ChartTooltipContent = ChartTooltipContent;
|
|
9060
12358
|
exports.Checkbox = Checkbox;
|
|
12359
|
+
exports.CircularProgress = CircularProgress;
|
|
9061
12360
|
exports.Collapsible = Collapsible;
|
|
9062
12361
|
exports.CollapsibleContent = CollapsibleContent2;
|
|
9063
12362
|
exports.CollapsibleTrigger = CollapsibleTrigger2;
|
|
@@ -9070,6 +12369,9 @@ exports.CommandItem = CommandItem;
|
|
|
9070
12369
|
exports.CommandList = CommandList;
|
|
9071
12370
|
exports.CommandSeparator = CommandSeparator;
|
|
9072
12371
|
exports.CommandShortcut = CommandShortcut;
|
|
12372
|
+
exports.CommentButton = CommentButton;
|
|
12373
|
+
exports.CommentDialog = CommentDialog;
|
|
12374
|
+
exports.CommentPopover = CommentPopover;
|
|
9073
12375
|
exports.ContextMenu = ContextMenu;
|
|
9074
12376
|
exports.ContextMenuCheckboxItem = ContextMenuCheckboxItem;
|
|
9075
12377
|
exports.ContextMenuContent = ContextMenuContent;
|
|
@@ -9087,8 +12389,13 @@ exports.ContextMenuSubTrigger = ContextMenuSubTrigger;
|
|
|
9087
12389
|
exports.ContextMenuTrigger = ContextMenuTrigger;
|
|
9088
12390
|
exports.DEFAULT_VISIBLE_HOURS = DEFAULT_VISIBLE_HOURS;
|
|
9089
12391
|
exports.DEFAULT_WORKING_HOURS = DEFAULT_WORKING_HOURS;
|
|
12392
|
+
exports.DataTableColumnHeader = DataTableColumnHeader;
|
|
12393
|
+
exports.DataTablePagination = DataTablePagination;
|
|
12394
|
+
exports.DataTableViewOptions = DataTableViewOptions;
|
|
9090
12395
|
exports.DateBadge = DateBadge;
|
|
9091
12396
|
exports.DayView = DayView;
|
|
12397
|
+
exports.DeliveryIndicator = DeliveryIndicator;
|
|
12398
|
+
exports.DeliveryIndicators = DeliveryIndicators;
|
|
9092
12399
|
exports.Dialog = Dialog;
|
|
9093
12400
|
exports.DialogClose = DialogClose;
|
|
9094
12401
|
exports.DialogContent = DialogContent;
|
|
@@ -9211,6 +12518,7 @@ exports.NavigationMenuLink = NavigationMenuLink;
|
|
|
9211
12518
|
exports.NavigationMenuList = NavigationMenuList;
|
|
9212
12519
|
exports.NavigationMenuTrigger = NavigationMenuTrigger;
|
|
9213
12520
|
exports.NavigationMenuViewport = NavigationMenuViewport;
|
|
12521
|
+
exports.NetBadge = NetBadge;
|
|
9214
12522
|
exports.Pagination = Pagination;
|
|
9215
12523
|
exports.PaginationContent = PaginationContent;
|
|
9216
12524
|
exports.PaginationEllipsis = PaginationEllipsis;
|
|
@@ -9218,6 +12526,9 @@ exports.PaginationItem = PaginationItem;
|
|
|
9218
12526
|
exports.PaginationLink = PaginationLink;
|
|
9219
12527
|
exports.PaginationNext = PaginationNext;
|
|
9220
12528
|
exports.PaginationPrevious = PaginationPrevious;
|
|
12529
|
+
exports.PlanningTable = PlanningTable;
|
|
12530
|
+
exports.PlanningTableToolbar = PlanningTableToolbar;
|
|
12531
|
+
exports.PlanningWeekCommentPopover = PlanningWeekCommentPopover;
|
|
9221
12532
|
exports.PlayerCanvas = PlayerCanvas;
|
|
9222
12533
|
exports.PlayerCanvasActionButton = PlayerCanvasActionButton;
|
|
9223
12534
|
exports.PlayerCanvasControls = PlayerCanvasControls;
|
|
@@ -9239,6 +12550,7 @@ exports.RadioGroupItem = RadioGroupItem;
|
|
|
9239
12550
|
exports.ResizableHandle = ResizableHandle;
|
|
9240
12551
|
exports.ResizablePanel = ResizablePanel;
|
|
9241
12552
|
exports.ResizablePanelGroup = ResizablePanelGroup;
|
|
12553
|
+
exports.RowHeaderCell = RowHeaderCell;
|
|
9242
12554
|
exports.ScrollArea = ScrollArea;
|
|
9243
12555
|
exports.ScrollBar = ScrollBar;
|
|
9244
12556
|
exports.SearchForm = SearchForm;
|
|
@@ -9296,6 +12608,8 @@ exports.SiteHeader = SiteHeader;
|
|
|
9296
12608
|
exports.Skeleton = Skeleton;
|
|
9297
12609
|
exports.Slider = Slider;
|
|
9298
12610
|
exports.Spinner = Spinner;
|
|
12611
|
+
exports.SubmitCalibrationBar = SubmitCalibrationBar;
|
|
12612
|
+
exports.SupplierCell = SupplierCell;
|
|
9299
12613
|
exports.Switch = Switch;
|
|
9300
12614
|
exports.Table = Table;
|
|
9301
12615
|
exports.TableBody = TableBody;
|
|
@@ -9326,21 +12640,35 @@ exports.TooltipProvider = TooltipProvider;
|
|
|
9326
12640
|
exports.TooltipTrigger = TooltipTrigger;
|
|
9327
12641
|
exports.UserAvatarsDropdown = UserAvatarsDropdown;
|
|
9328
12642
|
exports.VIEW_LABELS = VIEW_LABELS;
|
|
12643
|
+
exports.WeekCell = WeekCell;
|
|
12644
|
+
exports.WeekDetailDialog = WeekDetailDialog;
|
|
12645
|
+
exports.WeekHeader = WeekHeader;
|
|
9329
12646
|
exports.WeekView = WeekView;
|
|
9330
12647
|
exports.YearView = YearView;
|
|
9331
12648
|
exports.badgeVariants = badgeVariants;
|
|
9332
12649
|
exports.buttonGroupVariants = buttonGroupVariants;
|
|
9333
12650
|
exports.buttonVariants = buttonVariants;
|
|
12651
|
+
exports.calculateCalibrationCells = calculateCalibrationCells;
|
|
9334
12652
|
exports.calculateDropDates = calculateDropDates;
|
|
9335
12653
|
exports.calculateMonthEventPositions = calculateMonthEventPositions;
|
|
12654
|
+
exports.canSubmitCalibration = canSubmitCalibration;
|
|
9336
12655
|
exports.cardVariants = cardVariants;
|
|
9337
12656
|
exports.createDefaultEvent = createDefaultEvent;
|
|
9338
|
-
exports.
|
|
12657
|
+
exports.deliveryIndicatorVariants = deliveryIndicatorVariants;
|
|
12658
|
+
exports.formatCalibrationUnit = formatCalibrationUnit;
|
|
12659
|
+
exports.formatDateRange = formatDateRange2;
|
|
12660
|
+
exports.formatProductionUnit = formatProductionUnit;
|
|
9339
12661
|
exports.formatTime = formatTime;
|
|
12662
|
+
exports.generateColumns = generateColumns;
|
|
9340
12663
|
exports.generateEventId = generateEventId;
|
|
12664
|
+
exports.generateLocationOptions = generateLocationOptions;
|
|
12665
|
+
exports.generateWeekColumns = generateWeekColumns;
|
|
12666
|
+
exports.generateWeeks = generateWeeks;
|
|
9341
12667
|
exports.getCalendarCells = getCalendarCells;
|
|
12668
|
+
exports.getCommentLocationLabel = getCommentLocationLabel;
|
|
9342
12669
|
exports.getCurrentEvents = getCurrentEvents;
|
|
9343
12670
|
exports.getDayHours = getDayHours;
|
|
12671
|
+
exports.getElementShipmentStatus = getElementShipmentStatus;
|
|
9344
12672
|
exports.getEventBlockStyle = getEventBlockStyle;
|
|
9345
12673
|
exports.getEventDuration = getEventDuration;
|
|
9346
12674
|
exports.getEventDurationMinutes = getEventDurationMinutes;
|
|
@@ -9348,14 +12676,18 @@ exports.getEventsCount = getEventsCount;
|
|
|
9348
12676
|
exports.getEventsForDate = getEventsForDate;
|
|
9349
12677
|
exports.getEventsInRange = getEventsInRange;
|
|
9350
12678
|
exports.getHeaderLabel = getHeaderLabel;
|
|
12679
|
+
exports.getISOWeek = getISOWeek;
|
|
9351
12680
|
exports.getMonthCellEvents = getMonthCellEvents;
|
|
9352
12681
|
exports.getMonthDays = getMonthDays;
|
|
12682
|
+
exports.getShipmentStatusLabel = getShipmentStatusLabel;
|
|
12683
|
+
exports.getSupplierColumn = getSupplierColumn;
|
|
9353
12684
|
exports.getTimeHeight = getTimeHeight;
|
|
9354
12685
|
exports.getTimePosition = getTimePosition;
|
|
9355
12686
|
exports.getViewDateRange = getViewDateRange;
|
|
9356
12687
|
exports.getVisibleHours = getVisibleHours;
|
|
9357
12688
|
exports.getWeekDayNames = getWeekDayNames;
|
|
9358
12689
|
exports.getWeekDays = getWeekDays;
|
|
12690
|
+
exports.getWeekKey = getWeekKey;
|
|
9359
12691
|
exports.getYearMonths = getYearMonths;
|
|
9360
12692
|
exports.groupEvents = groupEvents;
|
|
9361
12693
|
exports.isMultiDayEvent = isMultiDayEvent;
|