@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.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React22 from 'react';
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
@@ -7,7 +7,7 @@ import { twMerge } from 'tailwind-merge';
|
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
9
9
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
10
|
-
import { SearchIcon, CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon, ChevronRightIcon, ChevronLeftIcon, ArrowLeft, ArrowRight, Loader2Icon, OctagonXIcon, TriangleAlertIcon, InfoIcon, CircleCheckIcon, ChevronRight, MoreHorizontal, MoreHorizontalIcon, XIcon, GripVerticalIcon, PanelLeftIcon, FolderIcon, ShareIcon, TrashIcon, ChevronsUpDownIcon, SparklesIcon, BadgeCheckIcon, CreditCardIcon, BellIcon, LogOutIcon,
|
|
10
|
+
import { SearchIcon, CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon, ChevronRightIcon, ChevronLeftIcon, ArrowLeft, ArrowRight, Check, Loader2Icon, OctagonXIcon, TriangleAlertIcon, InfoIcon, CircleCheckIcon, ChevronRight, MoreHorizontal, MoreHorizontalIcon, XIcon, GripVerticalIcon, PanelLeftIcon, ArrowDown, ArrowUp, ChevronsUpDown, EyeOff, ChevronsLeft, ChevronLeft, ChevronsRight, Settings2, FolderIcon, ShareIcon, TrashIcon, ChevronsUpDownIcon, SparklesIcon, BadgeCheckIcon, CreditCardIcon, BellIcon, LogOutIcon, X, Flag, Factory, Truck, MessageSquare, ChevronDown, Plus, Send, MessageSquarePlus, AlertTriangle, CheckCircle, Calendar as Calendar$1, User, Clock, CalendarX2, List, Columns, Grid2x2, Grid3x3, CalendarRange, Settings, Info, Moon, ArrowUpDown, CheckCircle2, XCircle, Package } from 'lucide-react';
|
|
11
11
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
12
12
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
13
13
|
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
@@ -39,14 +39,16 @@ import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
|
39
39
|
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
|
|
40
40
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
41
41
|
import * as ResizablePrimitive from 'react-resizable-panels';
|
|
42
|
+
import { useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
|
|
43
|
+
export { flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table';
|
|
42
44
|
import { subMonths, subYears, subWeeks, subDays, addMonths, addYears, addWeeks, addDays, format, startOfWeek, endOfWeek, startOfMonth, endOfMonth, startOfYear, endOfYear, isSameMonth, isSameWeek, isSameDay, isSameYear, isWithinInterval, parseISO, differenceInMinutes, eachDayOfInterval, differenceInDays, startOfDay, setMinutes, setHours, eachHourOfInterval, endOfDay, getHours, getMinutes, addMinutes, isToday, areIntervalsOverlapping } from 'date-fns';
|
|
43
45
|
export { areIntervalsOverlapping, format, getDay, isSameDay, isSameMonth, isToday, parseISO } from 'date-fns';
|
|
44
46
|
|
|
45
47
|
// src/hooks/use-mobile.ts
|
|
46
48
|
var MOBILE_BREAKPOINT = 768;
|
|
47
49
|
function useIsMobile() {
|
|
48
|
-
const [isMobile, setIsMobile] =
|
|
49
|
-
|
|
50
|
+
const [isMobile, setIsMobile] = React22.useState(void 0);
|
|
51
|
+
React22.useEffect(() => {
|
|
50
52
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
51
53
|
const onChange = () => {
|
|
52
54
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -87,7 +89,7 @@ var buttonVariants = cva(
|
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
);
|
|
90
|
-
var Button =
|
|
92
|
+
var Button = React22.forwardRef(
|
|
91
93
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
92
94
|
const Comp = asChild ? Slot : "button";
|
|
93
95
|
return /* @__PURE__ */ jsx(
|
|
@@ -451,7 +453,7 @@ function Slider({
|
|
|
451
453
|
max = 100,
|
|
452
454
|
...props
|
|
453
455
|
}) {
|
|
454
|
-
const _values =
|
|
456
|
+
const _values = React22.useMemo(
|
|
455
457
|
() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
|
|
456
458
|
[value, defaultValue, min, max]
|
|
457
459
|
);
|
|
@@ -737,7 +739,7 @@ function Toggle({
|
|
|
737
739
|
}
|
|
738
740
|
);
|
|
739
741
|
}
|
|
740
|
-
var ToggleGroupContext =
|
|
742
|
+
var ToggleGroupContext = React22.createContext({
|
|
741
743
|
size: "default",
|
|
742
744
|
variant: "default",
|
|
743
745
|
spacing: 0
|
|
@@ -774,7 +776,7 @@ function ToggleGroupItem({
|
|
|
774
776
|
size,
|
|
775
777
|
...props
|
|
776
778
|
}) {
|
|
777
|
-
const context =
|
|
779
|
+
const context = React22.useContext(ToggleGroupContext);
|
|
778
780
|
return /* @__PURE__ */ jsx(
|
|
779
781
|
ToggleGroupPrimitive.Item,
|
|
780
782
|
{
|
|
@@ -804,7 +806,7 @@ function ThemeSwitch({
|
|
|
804
806
|
className,
|
|
805
807
|
size = "default"
|
|
806
808
|
}) {
|
|
807
|
-
const [isChecked, setIsChecked] =
|
|
809
|
+
const [isChecked, setIsChecked] = React22.useState(defaultChecked);
|
|
808
810
|
const isControlled = checked !== void 0;
|
|
809
811
|
const currentChecked = isControlled ? checked : isChecked;
|
|
810
812
|
const handleClick = () => {
|
|
@@ -1224,7 +1226,7 @@ function Label2({
|
|
|
1224
1226
|
);
|
|
1225
1227
|
}
|
|
1226
1228
|
var Form = FormProvider;
|
|
1227
|
-
var FormFieldContext =
|
|
1229
|
+
var FormFieldContext = React22.createContext(
|
|
1228
1230
|
{}
|
|
1229
1231
|
);
|
|
1230
1232
|
var FormField = ({
|
|
@@ -1233,8 +1235,8 @@ var FormField = ({
|
|
|
1233
1235
|
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
1234
1236
|
};
|
|
1235
1237
|
var useFormField = () => {
|
|
1236
|
-
const fieldContext =
|
|
1237
|
-
const itemContext =
|
|
1238
|
+
const fieldContext = React22.useContext(FormFieldContext);
|
|
1239
|
+
const itemContext = React22.useContext(FormItemContext);
|
|
1238
1240
|
const { getFieldState } = useFormContext();
|
|
1239
1241
|
const formState = useFormState({ name: fieldContext.name });
|
|
1240
1242
|
const fieldState = getFieldState(fieldContext.name, formState);
|
|
@@ -1251,11 +1253,11 @@ var useFormField = () => {
|
|
|
1251
1253
|
...fieldState
|
|
1252
1254
|
};
|
|
1253
1255
|
};
|
|
1254
|
-
var FormItemContext =
|
|
1256
|
+
var FormItemContext = React22.createContext(
|
|
1255
1257
|
{}
|
|
1256
1258
|
);
|
|
1257
1259
|
function FormItem({ className, ...props }) {
|
|
1258
|
-
const id =
|
|
1260
|
+
const id = React22.useId();
|
|
1259
1261
|
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx(
|
|
1260
1262
|
"div",
|
|
1261
1263
|
{
|
|
@@ -2357,8 +2359,8 @@ function CalendarDayButton({
|
|
|
2357
2359
|
modifiers,
|
|
2358
2360
|
...props
|
|
2359
2361
|
}) {
|
|
2360
|
-
const ref =
|
|
2361
|
-
|
|
2362
|
+
const ref = React22.useRef(null);
|
|
2363
|
+
React22.useEffect(() => {
|
|
2362
2364
|
if (modifiers.focused) ref.current?.focus();
|
|
2363
2365
|
}, [modifiers.focused]);
|
|
2364
2366
|
return /* @__PURE__ */ jsx(
|
|
@@ -2379,9 +2381,9 @@ function CalendarDayButton({
|
|
|
2379
2381
|
}
|
|
2380
2382
|
);
|
|
2381
2383
|
}
|
|
2382
|
-
var CarouselContext =
|
|
2384
|
+
var CarouselContext = React22.createContext(null);
|
|
2383
2385
|
function useCarousel() {
|
|
2384
|
-
const context =
|
|
2386
|
+
const context = React22.useContext(CarouselContext);
|
|
2385
2387
|
if (!context) {
|
|
2386
2388
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
2387
2389
|
}
|
|
@@ -2403,20 +2405,20 @@ function Carousel({
|
|
|
2403
2405
|
},
|
|
2404
2406
|
plugins
|
|
2405
2407
|
);
|
|
2406
|
-
const [canScrollPrev, setCanScrollPrev] =
|
|
2407
|
-
const [canScrollNext, setCanScrollNext] =
|
|
2408
|
-
const onSelect =
|
|
2408
|
+
const [canScrollPrev, setCanScrollPrev] = React22.useState(false);
|
|
2409
|
+
const [canScrollNext, setCanScrollNext] = React22.useState(false);
|
|
2410
|
+
const onSelect = React22.useCallback((api2) => {
|
|
2409
2411
|
if (!api2) return;
|
|
2410
2412
|
setCanScrollPrev(api2.canScrollPrev());
|
|
2411
2413
|
setCanScrollNext(api2.canScrollNext());
|
|
2412
2414
|
}, []);
|
|
2413
|
-
const scrollPrev =
|
|
2415
|
+
const scrollPrev = React22.useCallback(() => {
|
|
2414
2416
|
api?.scrollPrev();
|
|
2415
2417
|
}, [api]);
|
|
2416
|
-
const scrollNext =
|
|
2418
|
+
const scrollNext = React22.useCallback(() => {
|
|
2417
2419
|
api?.scrollNext();
|
|
2418
2420
|
}, [api]);
|
|
2419
|
-
const handleKeyDown =
|
|
2421
|
+
const handleKeyDown = React22.useCallback(
|
|
2420
2422
|
(event) => {
|
|
2421
2423
|
if (event.key === "ArrowLeft") {
|
|
2422
2424
|
event.preventDefault();
|
|
@@ -2428,11 +2430,11 @@ function Carousel({
|
|
|
2428
2430
|
},
|
|
2429
2431
|
[scrollPrev, scrollNext]
|
|
2430
2432
|
);
|
|
2431
|
-
|
|
2433
|
+
React22.useEffect(() => {
|
|
2432
2434
|
if (!api || !setApi) return;
|
|
2433
2435
|
setApi(api);
|
|
2434
2436
|
}, [api, setApi]);
|
|
2435
|
-
|
|
2437
|
+
React22.useEffect(() => {
|
|
2436
2438
|
if (!api) return;
|
|
2437
2439
|
onSelect(api);
|
|
2438
2440
|
api.on("reInit", onSelect);
|
|
@@ -2565,9 +2567,9 @@ function CarouselNext({
|
|
|
2565
2567
|
);
|
|
2566
2568
|
}
|
|
2567
2569
|
var THEMES = { light: "", dark: ".dark" };
|
|
2568
|
-
var ChartContext =
|
|
2570
|
+
var ChartContext = React22.createContext(null);
|
|
2569
2571
|
function useChart() {
|
|
2570
|
-
const context =
|
|
2572
|
+
const context = React22.useContext(ChartContext);
|
|
2571
2573
|
if (!context) {
|
|
2572
2574
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
2573
2575
|
}
|
|
@@ -2580,7 +2582,7 @@ function ChartContainer({
|
|
|
2580
2582
|
config,
|
|
2581
2583
|
...props
|
|
2582
2584
|
}) {
|
|
2583
|
-
const uniqueId =
|
|
2585
|
+
const uniqueId = React22.useId();
|
|
2584
2586
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
2585
2587
|
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
2586
2588
|
"div",
|
|
@@ -2641,7 +2643,7 @@ function ChartTooltipContent({
|
|
|
2641
2643
|
labelKey
|
|
2642
2644
|
}) {
|
|
2643
2645
|
const { config } = useChart();
|
|
2644
|
-
const tooltipLabel =
|
|
2646
|
+
const tooltipLabel = React22.useMemo(() => {
|
|
2645
2647
|
if (hideLabel || !payload?.length) {
|
|
2646
2648
|
return null;
|
|
2647
2649
|
}
|
|
@@ -3297,6 +3299,105 @@ function Progress({
|
|
|
3297
3299
|
}
|
|
3298
3300
|
);
|
|
3299
3301
|
}
|
|
3302
|
+
function CircularProgress({
|
|
3303
|
+
className,
|
|
3304
|
+
value,
|
|
3305
|
+
size = 80,
|
|
3306
|
+
strokeWidth = 8,
|
|
3307
|
+
variant = "default",
|
|
3308
|
+
showCheckmark = true,
|
|
3309
|
+
children,
|
|
3310
|
+
...props
|
|
3311
|
+
}) {
|
|
3312
|
+
const clampedValue = Math.min(100, Math.max(0, value));
|
|
3313
|
+
const isComplete = clampedValue >= 100;
|
|
3314
|
+
const radius = (size - strokeWidth) / 2;
|
|
3315
|
+
const circumference = 2 * Math.PI * radius;
|
|
3316
|
+
const strokeDashoffset = circumference - clampedValue / 100 * circumference;
|
|
3317
|
+
const center = size / 2;
|
|
3318
|
+
const getVariantColors = () => {
|
|
3319
|
+
switch (variant) {
|
|
3320
|
+
case "success":
|
|
3321
|
+
return {
|
|
3322
|
+
track: "stroke-green-500/20",
|
|
3323
|
+
progress: "stroke-green-500",
|
|
3324
|
+
text: "text-green-600 dark:text-green-400"
|
|
3325
|
+
};
|
|
3326
|
+
case "warning":
|
|
3327
|
+
return {
|
|
3328
|
+
track: "stroke-amber-500/20",
|
|
3329
|
+
progress: "stroke-amber-500",
|
|
3330
|
+
text: "text-amber-600 dark:text-amber-400"
|
|
3331
|
+
};
|
|
3332
|
+
case "destructive":
|
|
3333
|
+
return {
|
|
3334
|
+
track: "stroke-red-500/20",
|
|
3335
|
+
progress: "stroke-red-500",
|
|
3336
|
+
text: "text-red-600 dark:text-red-400"
|
|
3337
|
+
};
|
|
3338
|
+
default:
|
|
3339
|
+
return {
|
|
3340
|
+
track: "stroke-primary/20",
|
|
3341
|
+
progress: "stroke-primary",
|
|
3342
|
+
text: "text-primary"
|
|
3343
|
+
};
|
|
3344
|
+
}
|
|
3345
|
+
};
|
|
3346
|
+
const colors = getVariantColors();
|
|
3347
|
+
return /* @__PURE__ */ jsxs(
|
|
3348
|
+
"div",
|
|
3349
|
+
{
|
|
3350
|
+
"data-slot": "circular-progress",
|
|
3351
|
+
"data-value": clampedValue,
|
|
3352
|
+
"data-complete": isComplete,
|
|
3353
|
+
className: cn("relative inline-flex items-center justify-center", className),
|
|
3354
|
+
style: { width: size, height: size },
|
|
3355
|
+
...props,
|
|
3356
|
+
children: [
|
|
3357
|
+
/* @__PURE__ */ jsxs(
|
|
3358
|
+
"svg",
|
|
3359
|
+
{
|
|
3360
|
+
className: "transform -rotate-90",
|
|
3361
|
+
width: size,
|
|
3362
|
+
height: size,
|
|
3363
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
3364
|
+
children: [
|
|
3365
|
+
/* @__PURE__ */ jsx(
|
|
3366
|
+
"circle",
|
|
3367
|
+
{
|
|
3368
|
+
className: cn("transition-all", colors.track),
|
|
3369
|
+
cx: center,
|
|
3370
|
+
cy: center,
|
|
3371
|
+
r: radius,
|
|
3372
|
+
fill: "none",
|
|
3373
|
+
strokeWidth
|
|
3374
|
+
}
|
|
3375
|
+
),
|
|
3376
|
+
/* @__PURE__ */ jsx(
|
|
3377
|
+
"circle",
|
|
3378
|
+
{
|
|
3379
|
+
className: cn("transition-all duration-300 ease-out", colors.progress),
|
|
3380
|
+
cx: center,
|
|
3381
|
+
cy: center,
|
|
3382
|
+
r: radius,
|
|
3383
|
+
fill: "none",
|
|
3384
|
+
strokeWidth,
|
|
3385
|
+
strokeLinecap: "round",
|
|
3386
|
+
strokeDasharray: circumference,
|
|
3387
|
+
strokeDashoffset
|
|
3388
|
+
}
|
|
3389
|
+
)
|
|
3390
|
+
]
|
|
3391
|
+
}
|
|
3392
|
+
),
|
|
3393
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: children ? children : isComplete && showCheckmark ? /* @__PURE__ */ jsx(Check, { className: cn("h-6 w-6", colors.text) }) : /* @__PURE__ */ jsxs("span", { className: cn("text-sm font-semibold tabular-nums", colors.text), children: [
|
|
3394
|
+
Math.round(clampedValue),
|
|
3395
|
+
"%"
|
|
3396
|
+
] }) })
|
|
3397
|
+
]
|
|
3398
|
+
}
|
|
3399
|
+
);
|
|
3400
|
+
}
|
|
3300
3401
|
function TooltipProvider({
|
|
3301
3402
|
delayDuration = 0,
|
|
3302
3403
|
...props
|
|
@@ -3344,8 +3445,8 @@ function TooltipContent({
|
|
|
3344
3445
|
) });
|
|
3345
3446
|
}
|
|
3346
3447
|
function useDetectTheme() {
|
|
3347
|
-
const [theme, setTheme] =
|
|
3348
|
-
|
|
3448
|
+
const [theme, setTheme] = React22.useState("light");
|
|
3449
|
+
React22.useEffect(() => {
|
|
3349
3450
|
const isDark = document.documentElement.classList.contains("dark");
|
|
3350
3451
|
setTheme(isDark ? "dark" : "light");
|
|
3351
3452
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -3397,6 +3498,81 @@ function Spinner({ className, ...props }) {
|
|
|
3397
3498
|
}
|
|
3398
3499
|
);
|
|
3399
3500
|
}
|
|
3501
|
+
var deliveryIndicatorVariants = cva(
|
|
3502
|
+
"inline-block rounded-full shrink-0",
|
|
3503
|
+
{
|
|
3504
|
+
variants: {
|
|
3505
|
+
status: {
|
|
3506
|
+
"on-time": "bg-[var(--j3m-green-9,#84EBB4)]",
|
|
3507
|
+
"delayed": "bg-[var(--j3m-yellow-9,#FFDB43)]",
|
|
3508
|
+
"critical": "bg-[var(--j3m-red-9,#FB3748)]",
|
|
3509
|
+
"pending": "bg-[var(--j3m-gray-6,#D2D2D2)]"
|
|
3510
|
+
},
|
|
3511
|
+
size: {
|
|
3512
|
+
sm: "h-1.5 w-3",
|
|
3513
|
+
default: "h-1.5 w-3",
|
|
3514
|
+
lg: "h-2 w-4"
|
|
3515
|
+
}
|
|
3516
|
+
},
|
|
3517
|
+
defaultVariants: {
|
|
3518
|
+
status: "pending",
|
|
3519
|
+
size: "default"
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
);
|
|
3523
|
+
function DeliveryIndicator({
|
|
3524
|
+
className,
|
|
3525
|
+
status,
|
|
3526
|
+
size,
|
|
3527
|
+
label,
|
|
3528
|
+
showTooltip = false,
|
|
3529
|
+
...props
|
|
3530
|
+
}) {
|
|
3531
|
+
const indicator = /* @__PURE__ */ jsx(
|
|
3532
|
+
"span",
|
|
3533
|
+
{
|
|
3534
|
+
"data-slot": "delivery-indicator",
|
|
3535
|
+
"data-status": status,
|
|
3536
|
+
className: cn(deliveryIndicatorVariants({ status, size }), className),
|
|
3537
|
+
"aria-label": label || `Delivery status: ${status}`,
|
|
3538
|
+
role: "img",
|
|
3539
|
+
...props
|
|
3540
|
+
}
|
|
3541
|
+
);
|
|
3542
|
+
if (showTooltip && label) {
|
|
3543
|
+
return /* @__PURE__ */ jsxs(Tooltip2, { children: [
|
|
3544
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: indicator }),
|
|
3545
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: label })
|
|
3546
|
+
] });
|
|
3547
|
+
}
|
|
3548
|
+
return indicator;
|
|
3549
|
+
}
|
|
3550
|
+
function DeliveryIndicators({
|
|
3551
|
+
className,
|
|
3552
|
+
deliveries,
|
|
3553
|
+
size = "default",
|
|
3554
|
+
showTooltips = false,
|
|
3555
|
+
...props
|
|
3556
|
+
}) {
|
|
3557
|
+
return /* @__PURE__ */ jsx(
|
|
3558
|
+
"div",
|
|
3559
|
+
{
|
|
3560
|
+
"data-slot": "delivery-indicators",
|
|
3561
|
+
className: cn("flex items-center gap-1", className),
|
|
3562
|
+
...props,
|
|
3563
|
+
children: deliveries.map((delivery, index) => /* @__PURE__ */ jsx(
|
|
3564
|
+
DeliveryIndicator,
|
|
3565
|
+
{
|
|
3566
|
+
status: delivery.status,
|
|
3567
|
+
size,
|
|
3568
|
+
label: delivery.label,
|
|
3569
|
+
showTooltip: showTooltips
|
|
3570
|
+
},
|
|
3571
|
+
index
|
|
3572
|
+
))
|
|
3573
|
+
}
|
|
3574
|
+
);
|
|
3575
|
+
}
|
|
3400
3576
|
function Breadcrumb({ ...props }) {
|
|
3401
3577
|
return /* @__PURE__ */ jsx("nav", { "aria-label": "breadcrumb", "data-slot": "breadcrumb", ...props });
|
|
3402
3578
|
}
|
|
@@ -3919,7 +4095,7 @@ function CommandShortcut({
|
|
|
3919
4095
|
}
|
|
3920
4096
|
);
|
|
3921
4097
|
}
|
|
3922
|
-
var SearchTrigger =
|
|
4098
|
+
var SearchTrigger = React22.forwardRef(
|
|
3923
4099
|
({
|
|
3924
4100
|
className,
|
|
3925
4101
|
placeholder = "Search...",
|
|
@@ -3955,7 +4131,7 @@ var SearchTrigger = React15.forwardRef(
|
|
|
3955
4131
|
);
|
|
3956
4132
|
SearchTrigger.displayName = "SearchTrigger";
|
|
3957
4133
|
function useSearchShortcut(onOpen, key = "k") {
|
|
3958
|
-
|
|
4134
|
+
React22.useEffect(() => {
|
|
3959
4135
|
const down = (e) => {
|
|
3960
4136
|
if (e.key.toLowerCase() === key.toLowerCase() && (e.metaKey || e.ctrlKey)) {
|
|
3961
4137
|
e.preventDefault();
|
|
@@ -4930,9 +5106,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
4930
5106
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
4931
5107
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
4932
5108
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
4933
|
-
var SidebarContext =
|
|
5109
|
+
var SidebarContext = React22.createContext(null);
|
|
4934
5110
|
function useSidebar() {
|
|
4935
|
-
const context =
|
|
5111
|
+
const context = React22.useContext(SidebarContext);
|
|
4936
5112
|
if (!context) {
|
|
4937
5113
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
4938
5114
|
}
|
|
@@ -4948,10 +5124,10 @@ function SidebarProvider({
|
|
|
4948
5124
|
...props
|
|
4949
5125
|
}) {
|
|
4950
5126
|
const isMobile = useIsMobile();
|
|
4951
|
-
const [openMobile, setOpenMobile] =
|
|
4952
|
-
const [_open, _setOpen] =
|
|
5127
|
+
const [openMobile, setOpenMobile] = React22.useState(false);
|
|
5128
|
+
const [_open, _setOpen] = React22.useState(defaultOpen);
|
|
4953
5129
|
const open = openProp ?? _open;
|
|
4954
|
-
const setOpen =
|
|
5130
|
+
const setOpen = React22.useCallback(
|
|
4955
5131
|
(value) => {
|
|
4956
5132
|
const openState = typeof value === "function" ? value(open) : value;
|
|
4957
5133
|
if (setOpenProp) {
|
|
@@ -4963,10 +5139,10 @@ function SidebarProvider({
|
|
|
4963
5139
|
},
|
|
4964
5140
|
[setOpenProp, open]
|
|
4965
5141
|
);
|
|
4966
|
-
const toggleSidebar =
|
|
5142
|
+
const toggleSidebar = React22.useCallback(() => {
|
|
4967
5143
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
4968
5144
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
4969
|
-
|
|
5145
|
+
React22.useEffect(() => {
|
|
4970
5146
|
const handleKeyDown = (event) => {
|
|
4971
5147
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
4972
5148
|
event.preventDefault();
|
|
@@ -4977,7 +5153,7 @@ function SidebarProvider({
|
|
|
4977
5153
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4978
5154
|
}, [toggleSidebar]);
|
|
4979
5155
|
const state = open ? "expanded" : "collapsed";
|
|
4980
|
-
const contextValue =
|
|
5156
|
+
const contextValue = React22.useMemo(
|
|
4981
5157
|
() => ({
|
|
4982
5158
|
state,
|
|
4983
5159
|
open,
|
|
@@ -5435,7 +5611,7 @@ function SidebarMenuSkeleton({
|
|
|
5435
5611
|
showIcon = false,
|
|
5436
5612
|
...props
|
|
5437
5613
|
}) {
|
|
5438
|
-
const width =
|
|
5614
|
+
const width = React22.useMemo(() => {
|
|
5439
5615
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
5440
5616
|
}, []);
|
|
5441
5617
|
return /* @__PURE__ */ jsxs(
|
|
@@ -5578,7 +5754,7 @@ var sectionVariants = cva(
|
|
|
5578
5754
|
}
|
|
5579
5755
|
);
|
|
5580
5756
|
var isGlassVariant = (variant) => variant?.startsWith("glass-") ?? false;
|
|
5581
|
-
var Section =
|
|
5757
|
+
var Section = React22.forwardRef(
|
|
5582
5758
|
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5583
5759
|
"section",
|
|
5584
5760
|
{
|
|
@@ -5590,7 +5766,7 @@ var Section = React15.forwardRef(
|
|
|
5590
5766
|
)
|
|
5591
5767
|
);
|
|
5592
5768
|
Section.displayName = "Section";
|
|
5593
|
-
var SectionHeader =
|
|
5769
|
+
var SectionHeader = React22.forwardRef(
|
|
5594
5770
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5595
5771
|
"div",
|
|
5596
5772
|
{
|
|
@@ -5605,7 +5781,7 @@ var SectionHeader = React15.forwardRef(
|
|
|
5605
5781
|
)
|
|
5606
5782
|
);
|
|
5607
5783
|
SectionHeader.displayName = "SectionHeader";
|
|
5608
|
-
var SectionTitle =
|
|
5784
|
+
var SectionTitle = React22.forwardRef(
|
|
5609
5785
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5610
5786
|
"h2",
|
|
5611
5787
|
{
|
|
@@ -5619,7 +5795,7 @@ var SectionTitle = React15.forwardRef(
|
|
|
5619
5795
|
)
|
|
5620
5796
|
);
|
|
5621
5797
|
SectionTitle.displayName = "SectionTitle";
|
|
5622
|
-
var SectionDescription =
|
|
5798
|
+
var SectionDescription = React22.forwardRef(
|
|
5623
5799
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5624
5800
|
"p",
|
|
5625
5801
|
{
|
|
@@ -5633,7 +5809,7 @@ var SectionDescription = React15.forwardRef(
|
|
|
5633
5809
|
)
|
|
5634
5810
|
);
|
|
5635
5811
|
SectionDescription.displayName = "SectionDescription";
|
|
5636
|
-
var SectionContent =
|
|
5812
|
+
var SectionContent = React22.forwardRef(
|
|
5637
5813
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5638
5814
|
"div",
|
|
5639
5815
|
{
|
|
@@ -5647,7 +5823,7 @@ var SectionContent = React15.forwardRef(
|
|
|
5647
5823
|
)
|
|
5648
5824
|
);
|
|
5649
5825
|
SectionContent.displayName = "SectionContent";
|
|
5650
|
-
var SectionFooter =
|
|
5826
|
+
var SectionFooter = React22.forwardRef(
|
|
5651
5827
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5652
5828
|
"div",
|
|
5653
5829
|
{
|
|
@@ -5663,6 +5839,180 @@ var SectionFooter = React15.forwardRef(
|
|
|
5663
5839
|
)
|
|
5664
5840
|
);
|
|
5665
5841
|
SectionFooter.displayName = "SectionFooter";
|
|
5842
|
+
function DataTableColumnHeader({
|
|
5843
|
+
column,
|
|
5844
|
+
title,
|
|
5845
|
+
className
|
|
5846
|
+
}) {
|
|
5847
|
+
if (!column.getCanSort()) {
|
|
5848
|
+
return /* @__PURE__ */ jsx("div", { className: cn(className), children: title });
|
|
5849
|
+
}
|
|
5850
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5851
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
5852
|
+
Button,
|
|
5853
|
+
{
|
|
5854
|
+
variant: "ghost",
|
|
5855
|
+
size: "sm",
|
|
5856
|
+
className: "data-[state=open]:bg-accent -ml-3 h-8",
|
|
5857
|
+
children: [
|
|
5858
|
+
/* @__PURE__ */ jsx("span", { children: title }),
|
|
5859
|
+
column.getIsSorted() === "desc" ? /* @__PURE__ */ jsx(ArrowDown, {}) : column.getIsSorted() === "asc" ? /* @__PURE__ */ jsx(ArrowUp, {}) : /* @__PURE__ */ jsx(ChevronsUpDown, {})
|
|
5860
|
+
]
|
|
5861
|
+
}
|
|
5862
|
+
) }),
|
|
5863
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", children: [
|
|
5864
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => column.toggleSorting(false), children: [
|
|
5865
|
+
/* @__PURE__ */ jsx(ArrowUp, {}),
|
|
5866
|
+
"Asc"
|
|
5867
|
+
] }),
|
|
5868
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => column.toggleSorting(true), children: [
|
|
5869
|
+
/* @__PURE__ */ jsx(ArrowDown, {}),
|
|
5870
|
+
"Desc"
|
|
5871
|
+
] }),
|
|
5872
|
+
column.getCanHide() && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5873
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5874
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => column.toggleVisibility(false), children: [
|
|
5875
|
+
/* @__PURE__ */ jsx(EyeOff, {}),
|
|
5876
|
+
"Hide"
|
|
5877
|
+
] })
|
|
5878
|
+
] })
|
|
5879
|
+
] })
|
|
5880
|
+
] }) });
|
|
5881
|
+
}
|
|
5882
|
+
function DataTablePagination({
|
|
5883
|
+
table,
|
|
5884
|
+
showRowSelection = true,
|
|
5885
|
+
pageSizeOptions = [10, 20, 25, 30, 40, 50]
|
|
5886
|
+
}) {
|
|
5887
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-2", children: [
|
|
5888
|
+
showRowSelection && /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground flex-1 text-sm", children: [
|
|
5889
|
+
table.getFilteredSelectedRowModel().rows.length,
|
|
5890
|
+
" of",
|
|
5891
|
+
" ",
|
|
5892
|
+
table.getFilteredRowModel().rows.length,
|
|
5893
|
+
" row(s) selected."
|
|
5894
|
+
] }),
|
|
5895
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-6 lg:space-x-8", children: [
|
|
5896
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
5897
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Rows per page" }),
|
|
5898
|
+
/* @__PURE__ */ jsxs(
|
|
5899
|
+
Select,
|
|
5900
|
+
{
|
|
5901
|
+
value: `${table.getState().pagination.pageSize}`,
|
|
5902
|
+
onValueChange: (value) => {
|
|
5903
|
+
table.setPageSize(Number(value));
|
|
5904
|
+
},
|
|
5905
|
+
children: [
|
|
5906
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: table.getState().pagination.pageSize }) }),
|
|
5907
|
+
/* @__PURE__ */ jsx(SelectContent, { side: "top", children: pageSizeOptions.map((pageSize) => /* @__PURE__ */ jsx(SelectItem, { value: `${pageSize}`, children: pageSize }, pageSize)) })
|
|
5908
|
+
]
|
|
5909
|
+
}
|
|
5910
|
+
)
|
|
5911
|
+
] }),
|
|
5912
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-[100px] items-center justify-center text-sm font-medium", children: [
|
|
5913
|
+
"Page ",
|
|
5914
|
+
table.getState().pagination.pageIndex + 1,
|
|
5915
|
+
" of",
|
|
5916
|
+
" ",
|
|
5917
|
+
table.getPageCount()
|
|
5918
|
+
] }),
|
|
5919
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
5920
|
+
/* @__PURE__ */ jsxs(
|
|
5921
|
+
Button,
|
|
5922
|
+
{
|
|
5923
|
+
variant: "outline",
|
|
5924
|
+
size: "icon",
|
|
5925
|
+
className: "hidden size-8 lg:flex",
|
|
5926
|
+
onClick: () => table.setPageIndex(0),
|
|
5927
|
+
disabled: !table.getCanPreviousPage(),
|
|
5928
|
+
children: [
|
|
5929
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Go to first page" }),
|
|
5930
|
+
/* @__PURE__ */ jsx(ChevronsLeft, {})
|
|
5931
|
+
]
|
|
5932
|
+
}
|
|
5933
|
+
),
|
|
5934
|
+
/* @__PURE__ */ jsxs(
|
|
5935
|
+
Button,
|
|
5936
|
+
{
|
|
5937
|
+
variant: "outline",
|
|
5938
|
+
size: "icon",
|
|
5939
|
+
className: "size-8",
|
|
5940
|
+
onClick: () => table.previousPage(),
|
|
5941
|
+
disabled: !table.getCanPreviousPage(),
|
|
5942
|
+
children: [
|
|
5943
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Go to previous page" }),
|
|
5944
|
+
/* @__PURE__ */ jsx(ChevronLeft, {})
|
|
5945
|
+
]
|
|
5946
|
+
}
|
|
5947
|
+
),
|
|
5948
|
+
/* @__PURE__ */ jsxs(
|
|
5949
|
+
Button,
|
|
5950
|
+
{
|
|
5951
|
+
variant: "outline",
|
|
5952
|
+
size: "icon",
|
|
5953
|
+
className: "size-8",
|
|
5954
|
+
onClick: () => table.nextPage(),
|
|
5955
|
+
disabled: !table.getCanNextPage(),
|
|
5956
|
+
children: [
|
|
5957
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Go to next page" }),
|
|
5958
|
+
/* @__PURE__ */ jsx(ChevronRight, {})
|
|
5959
|
+
]
|
|
5960
|
+
}
|
|
5961
|
+
),
|
|
5962
|
+
/* @__PURE__ */ jsxs(
|
|
5963
|
+
Button,
|
|
5964
|
+
{
|
|
5965
|
+
variant: "outline",
|
|
5966
|
+
size: "icon",
|
|
5967
|
+
className: "hidden size-8 lg:flex",
|
|
5968
|
+
onClick: () => table.setPageIndex(table.getPageCount() - 1),
|
|
5969
|
+
disabled: !table.getCanNextPage(),
|
|
5970
|
+
children: [
|
|
5971
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Go to last page" }),
|
|
5972
|
+
/* @__PURE__ */ jsx(ChevronsRight, {})
|
|
5973
|
+
]
|
|
5974
|
+
}
|
|
5975
|
+
)
|
|
5976
|
+
] })
|
|
5977
|
+
] })
|
|
5978
|
+
] });
|
|
5979
|
+
}
|
|
5980
|
+
function DataTableViewOptions({
|
|
5981
|
+
table
|
|
5982
|
+
}) {
|
|
5983
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5984
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
5985
|
+
Button,
|
|
5986
|
+
{
|
|
5987
|
+
variant: "outline",
|
|
5988
|
+
size: "sm",
|
|
5989
|
+
className: "ml-auto hidden h-8 lg:flex",
|
|
5990
|
+
children: [
|
|
5991
|
+
/* @__PURE__ */ jsx(Settings2, {}),
|
|
5992
|
+
"View"
|
|
5993
|
+
]
|
|
5994
|
+
}
|
|
5995
|
+
) }),
|
|
5996
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-[150px]", children: [
|
|
5997
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Toggle columns" }),
|
|
5998
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5999
|
+
table.getAllColumns().filter(
|
|
6000
|
+
(column) => typeof column.accessorFn !== "undefined" && column.getCanHide()
|
|
6001
|
+
).map((column) => {
|
|
6002
|
+
return /* @__PURE__ */ jsx(
|
|
6003
|
+
DropdownMenuCheckboxItem,
|
|
6004
|
+
{
|
|
6005
|
+
className: "capitalize",
|
|
6006
|
+
checked: column.getIsVisible(),
|
|
6007
|
+
onCheckedChange: (value) => column.toggleVisibility(!!value),
|
|
6008
|
+
children: column.id
|
|
6009
|
+
},
|
|
6010
|
+
column.id
|
|
6011
|
+
);
|
|
6012
|
+
})
|
|
6013
|
+
] })
|
|
6014
|
+
] });
|
|
6015
|
+
}
|
|
5666
6016
|
function SearchForm({ ...props }) {
|
|
5667
6017
|
return /* @__PURE__ */ jsx("form", { ...props, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5668
6018
|
/* @__PURE__ */ jsx(Label2, { htmlFor: "search", className: "sr-only", children: "Search" }),
|
|
@@ -5698,7 +6048,7 @@ function SiteHeader({
|
|
|
5698
6048
|
children: /* @__PURE__ */ 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: [
|
|
5699
6049
|
trigger,
|
|
5700
6050
|
trigger && /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-[var(--j3m-spacing-s)] h-4" }),
|
|
5701
|
-
/* @__PURE__ */ jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxs(
|
|
6051
|
+
/* @__PURE__ */ jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxs(React22.Fragment, { children: [
|
|
5702
6052
|
index > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
|
|
5703
6053
|
/* @__PURE__ */ jsx(BreadcrumbItem, { children: item.href ? /* @__PURE__ */ jsx(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) })
|
|
5704
6054
|
] }, index)) }) }),
|
|
@@ -5847,116 +6197,3038 @@ function NavUser({ user }) {
|
|
|
5847
6197
|
)
|
|
5848
6198
|
] }) }) });
|
|
5849
6199
|
}
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
6200
|
+
function PlanningTableToolbar({
|
|
6201
|
+
className,
|
|
6202
|
+
table,
|
|
6203
|
+
...props
|
|
6204
|
+
}) {
|
|
6205
|
+
const isFiltered = table.getState().columnFilters.length > 0;
|
|
6206
|
+
return /* @__PURE__ */ jsxs(
|
|
6207
|
+
"div",
|
|
6208
|
+
{
|
|
6209
|
+
"data-slot": "planning-table-toolbar",
|
|
6210
|
+
className: cn("flex items-center gap-2", className),
|
|
6211
|
+
...props,
|
|
6212
|
+
children: [
|
|
6213
|
+
/* @__PURE__ */ jsx(
|
|
6214
|
+
Input,
|
|
6215
|
+
{
|
|
6216
|
+
placeholder: "Filter suppliers...",
|
|
6217
|
+
value: table.getColumn("supplier")?.getFilterValue() ?? "",
|
|
6218
|
+
onChange: (event) => table.getColumn("supplier")?.setFilterValue(event.target.value),
|
|
6219
|
+
className: "h-8 w-[150px] lg:w-[250px]"
|
|
6220
|
+
}
|
|
6221
|
+
),
|
|
6222
|
+
isFiltered && /* @__PURE__ */ jsxs(
|
|
6223
|
+
Button,
|
|
6224
|
+
{
|
|
6225
|
+
variant: "ghost",
|
|
6226
|
+
onClick: () => table.resetColumnFilters(),
|
|
6227
|
+
className: "h-8 px-2 lg:px-3",
|
|
6228
|
+
children: [
|
|
6229
|
+
"Reset",
|
|
6230
|
+
/* @__PURE__ */ jsx(X, { className: "ml-2 h-4 w-4" })
|
|
6231
|
+
]
|
|
6232
|
+
}
|
|
6233
|
+
)
|
|
6234
|
+
]
|
|
6235
|
+
}
|
|
6236
|
+
);
|
|
6237
|
+
}
|
|
6238
|
+
function getBadgeVariant(badgeType) {
|
|
6239
|
+
return "outline";
|
|
6240
|
+
}
|
|
6241
|
+
function SupplierCell({
|
|
6242
|
+
className,
|
|
6243
|
+
supplier,
|
|
6244
|
+
...props
|
|
6245
|
+
}) {
|
|
6246
|
+
const spacingClasses = "px-[var(--j3m-spacing-xs)] pt-[var(--j3m-spacing-s)] pb-2";
|
|
6247
|
+
return /* @__PURE__ */ jsx(
|
|
6248
|
+
"div",
|
|
6249
|
+
{
|
|
6250
|
+
"data-slot": "supplier-cell",
|
|
6251
|
+
className: cn(
|
|
6252
|
+
// Same height as WeekCell (80px) for row alignment
|
|
6253
|
+
"flex flex-col justify-center gap-1.5 min-w-[200px] h-[80px]",
|
|
6254
|
+
// White background for Y-axis legend cells
|
|
6255
|
+
"bg-background",
|
|
6256
|
+
spacingClasses,
|
|
6257
|
+
className
|
|
6258
|
+
),
|
|
6259
|
+
...props,
|
|
6260
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
6261
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
6262
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: supplier.name }),
|
|
6263
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: supplier.scope })
|
|
6264
|
+
] }),
|
|
6265
|
+
/* @__PURE__ */ jsxs(
|
|
6266
|
+
Badge,
|
|
6267
|
+
{
|
|
6268
|
+
variant: getBadgeVariant(supplier.badgeType),
|
|
6269
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
6270
|
+
children: [
|
|
6271
|
+
/* @__PURE__ */ jsx(Flag, { className: "h-2.5 w-2.5" }),
|
|
6272
|
+
supplier.badgeType
|
|
6273
|
+
]
|
|
6274
|
+
}
|
|
6275
|
+
)
|
|
6276
|
+
] })
|
|
6277
|
+
}
|
|
6278
|
+
);
|
|
6279
|
+
}
|
|
6280
|
+
function getCombinedRiskLevel(data) {
|
|
6281
|
+
const productionStatus = data.production?.status || "on-time";
|
|
6282
|
+
const hasDeliveryCritical = data.deliveries?.some((d) => d.status === "critical");
|
|
6283
|
+
const hasDeliveryDelayed = data.deliveries?.some((d) => d.status === "delayed");
|
|
6284
|
+
if (productionStatus === "critical" || hasDeliveryCritical) {
|
|
6285
|
+
return "critical";
|
|
6286
|
+
}
|
|
6287
|
+
if (productionStatus === "delayed" || hasDeliveryDelayed || data.hasWarning) {
|
|
6288
|
+
return "warning";
|
|
6289
|
+
}
|
|
6290
|
+
return "normal";
|
|
6291
|
+
}
|
|
6292
|
+
function getRowStatus(status) {
|
|
6293
|
+
if (status === "critical") return "critical";
|
|
6294
|
+
if (status === "delayed") return "warning";
|
|
6295
|
+
return "normal";
|
|
6296
|
+
}
|
|
6297
|
+
var statusFillClasses = {
|
|
6298
|
+
normal: {
|
|
6299
|
+
border: "border-l-[3px] border-l-green-500",
|
|
6300
|
+
bg: "bg-green-50/50 dark:bg-green-950/30"
|
|
5879
6301
|
},
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
border: "border-red-500"
|
|
6302
|
+
warning: {
|
|
6303
|
+
border: "border-l-[3px] border-l-amber-500",
|
|
6304
|
+
bg: "bg-amber-50/50 dark:bg-amber-950/30"
|
|
5884
6305
|
},
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
6306
|
+
critical: {
|
|
6307
|
+
border: "border-l-[3px] border-l-red-500",
|
|
6308
|
+
bg: "bg-red-50/50 dark:bg-red-950/30"
|
|
6309
|
+
}
|
|
6310
|
+
};
|
|
6311
|
+
var statusColors = {
|
|
6312
|
+
normal: {
|
|
6313
|
+
icon: "text-green-600 dark:text-green-400",
|
|
6314
|
+
progress: "bg-green-500",
|
|
6315
|
+
text: "text-green-700 dark:text-green-300"
|
|
5889
6316
|
},
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
6317
|
+
warning: {
|
|
6318
|
+
icon: "text-amber-600 dark:text-amber-400",
|
|
6319
|
+
progress: "bg-amber-500",
|
|
6320
|
+
text: "text-amber-700 dark:text-amber-300"
|
|
5894
6321
|
},
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
6322
|
+
critical: {
|
|
6323
|
+
icon: "text-red-600 dark:text-red-400",
|
|
6324
|
+
progress: "bg-red-500",
|
|
6325
|
+
text: "text-red-700 dark:text-red-300"
|
|
5899
6326
|
}
|
|
5900
6327
|
};
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
6328
|
+
function WeekCell({
|
|
6329
|
+
className,
|
|
6330
|
+
data,
|
|
6331
|
+
week,
|
|
6332
|
+
supplier,
|
|
6333
|
+
isCurrentWeek,
|
|
6334
|
+
onCellClick,
|
|
6335
|
+
...props
|
|
6336
|
+
}) {
|
|
6337
|
+
const combinedRisk = data.type === "data" ? getCombinedRiskLevel(data) : "normal";
|
|
6338
|
+
const statusClasses = statusFillClasses[combinedRisk];
|
|
6339
|
+
const productionProgress = data.production?.progress ?? data.progress ?? 0;
|
|
6340
|
+
const productionStatus = getRowStatus(data.production?.status);
|
|
6341
|
+
const productionColors = statusColors[productionStatus];
|
|
6342
|
+
const deliveryCount = data.deliveries?.length ?? 0;
|
|
6343
|
+
const worstDeliveryStatus = data.deliveries?.some((d) => d.status === "critical") ? "critical" : data.deliveries?.some((d) => d.status === "delayed") ? "warning" : "normal";
|
|
6344
|
+
const deliveryColors = statusColors[worstDeliveryStatus];
|
|
6345
|
+
const getDeliveryStatusColor = (status) => {
|
|
6346
|
+
switch (status) {
|
|
6347
|
+
case "critical":
|
|
6348
|
+
return "bg-red-500";
|
|
6349
|
+
case "delayed":
|
|
6350
|
+
return "bg-amber-500";
|
|
6351
|
+
default:
|
|
6352
|
+
return "bg-green-500";
|
|
6353
|
+
}
|
|
6354
|
+
};
|
|
6355
|
+
const handleClick = () => {
|
|
6356
|
+
if (onCellClick && data.type !== "empty") {
|
|
6357
|
+
onCellClick();
|
|
6358
|
+
}
|
|
6359
|
+
};
|
|
6360
|
+
const handleKeyDown = (e) => {
|
|
6361
|
+
if ((e.key === "Enter" || e.key === " ") && onCellClick && data.type !== "empty") {
|
|
6362
|
+
e.preventDefault();
|
|
6363
|
+
onCellClick();
|
|
6364
|
+
}
|
|
6365
|
+
};
|
|
6366
|
+
const spacingClasses = "px-[var(--j3m-spacing-xs)] pt-[var(--j3m-spacing-s)] pb-2";
|
|
6367
|
+
if (data.type === "empty") {
|
|
6368
|
+
return /* @__PURE__ */ jsx(
|
|
6369
|
+
"div",
|
|
6370
|
+
{
|
|
6371
|
+
"data-slot": "week-cell",
|
|
6372
|
+
"data-state": "empty",
|
|
6373
|
+
"data-current-week": isCurrentWeek,
|
|
6374
|
+
className: cn(
|
|
6375
|
+
"flex h-[80px] items-center justify-center cursor-default",
|
|
6376
|
+
"bg-background",
|
|
6377
|
+
spacingClasses,
|
|
6378
|
+
className
|
|
6379
|
+
),
|
|
6380
|
+
...props,
|
|
6381
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/30 text-xl", children: "\xB7" })
|
|
6382
|
+
}
|
|
6383
|
+
);
|
|
6384
|
+
}
|
|
6385
|
+
if (data.type === "no-logistics") {
|
|
6386
|
+
return /* @__PURE__ */ jsxs(
|
|
6387
|
+
"div",
|
|
6388
|
+
{
|
|
6389
|
+
"data-slot": "week-cell",
|
|
6390
|
+
"data-state": "no-logistics",
|
|
6391
|
+
"data-current-week": isCurrentWeek,
|
|
6392
|
+
onClick: handleClick,
|
|
6393
|
+
onKeyDown: handleKeyDown,
|
|
6394
|
+
role: "button",
|
|
6395
|
+
tabIndex: 0,
|
|
6396
|
+
className: cn(
|
|
6397
|
+
"flex flex-col h-[80px] justify-center gap-2",
|
|
6398
|
+
"cursor-pointer bg-background",
|
|
6399
|
+
"border-l-[3px] border-l-muted-foreground/30",
|
|
6400
|
+
spacingClasses,
|
|
6401
|
+
// Hover lift effect
|
|
6402
|
+
"transition-all duration-200 ease-out",
|
|
6403
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
6404
|
+
className
|
|
6405
|
+
),
|
|
6406
|
+
...props,
|
|
6407
|
+
children: [
|
|
6408
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6409
|
+
/* @__PURE__ */ jsx(Factory, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
6410
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 h-1.5 bg-muted-foreground/20 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
6411
|
+
"div",
|
|
6412
|
+
{
|
|
6413
|
+
className: "h-full bg-muted-foreground/40 rounded-full",
|
|
6414
|
+
style: { width: `${productionProgress}%` }
|
|
6415
|
+
}
|
|
6416
|
+
) })
|
|
6417
|
+
] }),
|
|
6418
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
|
|
6419
|
+
/* @__PURE__ */ jsx(Truck, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
6420
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px]", children: "No logistics" })
|
|
6421
|
+
] })
|
|
6422
|
+
]
|
|
6423
|
+
}
|
|
6424
|
+
);
|
|
6425
|
+
}
|
|
6426
|
+
return /* @__PURE__ */ jsxs(
|
|
6427
|
+
"div",
|
|
6428
|
+
{
|
|
6429
|
+
"data-slot": "week-cell",
|
|
6430
|
+
"data-state": "data",
|
|
6431
|
+
"data-risk": combinedRisk,
|
|
6432
|
+
"data-current-week": isCurrentWeek,
|
|
6433
|
+
onClick: handleClick,
|
|
6434
|
+
onKeyDown: handleKeyDown,
|
|
6435
|
+
role: "button",
|
|
6436
|
+
tabIndex: 0,
|
|
6437
|
+
className: cn(
|
|
6438
|
+
"flex flex-col h-[80px] justify-center gap-2",
|
|
6439
|
+
"cursor-pointer",
|
|
6440
|
+
// Edge-to-edge status fill (no inset card)
|
|
6441
|
+
statusClasses.border,
|
|
6442
|
+
statusClasses.bg,
|
|
6443
|
+
spacingClasses,
|
|
6444
|
+
// Hover lift effect
|
|
6445
|
+
"transition-all duration-200 ease-out",
|
|
6446
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
6447
|
+
className
|
|
6448
|
+
),
|
|
6449
|
+
...props,
|
|
6450
|
+
children: [
|
|
6451
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6452
|
+
/* @__PURE__ */ jsx(Factory, { className: cn("h-3.5 w-3.5 shrink-0", productionColors.icon) }),
|
|
6453
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
6454
|
+
"div",
|
|
6455
|
+
{
|
|
6456
|
+
className: cn("h-full rounded-full transition-all", productionColors.progress),
|
|
6457
|
+
style: { width: `${productionProgress}%` }
|
|
6458
|
+
}
|
|
6459
|
+
) })
|
|
6460
|
+
] }),
|
|
6461
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6462
|
+
/* @__PURE__ */ jsx(Truck, { className: cn("h-3.5 w-3.5 shrink-0", deliveryColors.icon) }),
|
|
6463
|
+
deliveryCount > 0 ? /* @__PURE__ */ jsxs("span", { className: cn("text-[10px] font-medium", deliveryColors.text), children: [
|
|
6464
|
+
deliveryCount,
|
|
6465
|
+
"x delivery"
|
|
6466
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2014" })
|
|
6467
|
+
] }),
|
|
6468
|
+
deliveryCount > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6469
|
+
data.deliveries?.slice(0, 5).map((delivery, index) => {
|
|
6470
|
+
const deliveryProgress = delivery.progress ?? (delivery.status === "on-time" ? 100 : delivery.status === "delayed" ? 50 : 25);
|
|
6471
|
+
return /* @__PURE__ */ jsx(
|
|
6472
|
+
"div",
|
|
6473
|
+
{
|
|
6474
|
+
className: "flex-1 max-w-[24px]",
|
|
6475
|
+
title: delivery.label || `Delivery ${index + 1}`,
|
|
6476
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-1 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
6477
|
+
"div",
|
|
6478
|
+
{
|
|
6479
|
+
className: cn("h-full rounded-full transition-all", getDeliveryStatusColor(delivery.status)),
|
|
6480
|
+
style: { width: `${deliveryProgress}%` }
|
|
6481
|
+
}
|
|
6482
|
+
) })
|
|
6483
|
+
},
|
|
6484
|
+
delivery.id || index
|
|
6485
|
+
);
|
|
6486
|
+
}),
|
|
6487
|
+
deliveryCount > 5 && /* @__PURE__ */ jsxs("span", { className: "text-[8px] text-muted-foreground", children: [
|
|
6488
|
+
"+",
|
|
6489
|
+
deliveryCount - 5
|
|
6490
|
+
] })
|
|
6491
|
+
] })
|
|
6492
|
+
]
|
|
6493
|
+
}
|
|
6494
|
+
);
|
|
6495
|
+
}
|
|
6496
|
+
function CommentButton({
|
|
6497
|
+
className,
|
|
6498
|
+
commentCount = 0,
|
|
6499
|
+
size = "default",
|
|
6500
|
+
...props
|
|
6501
|
+
}) {
|
|
6502
|
+
const hasComments = commentCount > 0;
|
|
6503
|
+
const sizeClasses = size === "sm" ? "h-6 w-6" : "h-7 w-7";
|
|
6504
|
+
const iconSize = size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4";
|
|
6505
|
+
return /* @__PURE__ */ jsxs(
|
|
6506
|
+
Button,
|
|
6507
|
+
{
|
|
6508
|
+
variant: "outline",
|
|
6509
|
+
size: "icon",
|
|
6510
|
+
className: cn(
|
|
6511
|
+
sizeClasses,
|
|
6512
|
+
"rounded-full shrink-0 relative",
|
|
6513
|
+
"border-border bg-background hover:bg-muted",
|
|
6514
|
+
"shadow-[var(--j3m-shadow-sm)]",
|
|
6515
|
+
hasComments && "border-primary/50",
|
|
6516
|
+
className
|
|
6517
|
+
),
|
|
6518
|
+
...props,
|
|
6519
|
+
children: [
|
|
6520
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: cn(iconSize, hasComments && "text-primary") }),
|
|
6521
|
+
hasComments && /* @__PURE__ */ jsx(
|
|
6522
|
+
"span",
|
|
6523
|
+
{
|
|
6524
|
+
className: cn(
|
|
6525
|
+
"absolute -top-0.5 -right-0.5",
|
|
6526
|
+
"h-2.5 w-2.5 rounded-full",
|
|
6527
|
+
"bg-primary",
|
|
6528
|
+
"border border-background"
|
|
6529
|
+
// Subtle outline for contrast
|
|
6530
|
+
),
|
|
6531
|
+
"aria-hidden": "true"
|
|
6532
|
+
}
|
|
6533
|
+
),
|
|
6534
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: hasComments ? `${commentCount} comment${commentCount > 1 ? "s" : ""}` : "Add comment" })
|
|
6535
|
+
]
|
|
6536
|
+
}
|
|
6537
|
+
);
|
|
6538
|
+
}
|
|
6539
|
+
|
|
6540
|
+
// src/blocks/planning-table/types.ts
|
|
6541
|
+
function getCommentLocationLabel(location) {
|
|
6542
|
+
if (location.type === "production") {
|
|
6543
|
+
return location.supplierName ? `Production - ${location.supplierName}` : "Production";
|
|
6544
|
+
}
|
|
6545
|
+
if (location.type === "delivery") {
|
|
6546
|
+
return location.deliveryLabel || `Delivery ${location.deliveryId || ""}`;
|
|
6547
|
+
}
|
|
6548
|
+
return "Unknown";
|
|
6549
|
+
}
|
|
6550
|
+
function getElementShipmentStatus(element, currentDeliveryId) {
|
|
6551
|
+
if (element.shipmentStatus) {
|
|
6552
|
+
return element.shipmentStatus;
|
|
6553
|
+
}
|
|
6554
|
+
if (element.isProduced) {
|
|
6555
|
+
if (element.actualDeliveryId && element.actualDeliveryId !== currentDeliveryId) {
|
|
6556
|
+
return "moved";
|
|
6557
|
+
}
|
|
6558
|
+
return "sent";
|
|
6559
|
+
}
|
|
6560
|
+
if (element.originalDeliveryId && element.originalDeliveryId !== currentDeliveryId) {
|
|
6561
|
+
return "addon";
|
|
6562
|
+
}
|
|
6563
|
+
return "not-sent";
|
|
6564
|
+
}
|
|
6565
|
+
function getShipmentStatusLabel(status) {
|
|
6566
|
+
switch (status) {
|
|
6567
|
+
case "sent":
|
|
6568
|
+
return "Sent";
|
|
6569
|
+
case "not-sent":
|
|
6570
|
+
return "Missing";
|
|
6571
|
+
// Neutral tone, not "Not sent"
|
|
6572
|
+
case "moved":
|
|
6573
|
+
return "Moved to another delivery";
|
|
6574
|
+
case "addon":
|
|
6575
|
+
return "Add-on";
|
|
6576
|
+
case "planned":
|
|
6577
|
+
return "Planned";
|
|
6578
|
+
default:
|
|
6579
|
+
return status;
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
function getWeekKey(date) {
|
|
6583
|
+
const year = date.getFullYear();
|
|
6584
|
+
const weekNumber = getISOWeek(date);
|
|
6585
|
+
return `${year}-W${weekNumber.toString().padStart(2, "0")}`;
|
|
6586
|
+
}
|
|
6587
|
+
function getISOWeek(date) {
|
|
6588
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
6589
|
+
const dayNum = d.getUTCDay() || 7;
|
|
6590
|
+
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
6591
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
6592
|
+
return Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
6593
|
+
}
|
|
6594
|
+
function generateWeeks(startDate, count) {
|
|
6595
|
+
const weeks = [];
|
|
6596
|
+
const current = new Date(startDate);
|
|
6597
|
+
const today = /* @__PURE__ */ new Date();
|
|
6598
|
+
const currentWeekKey = getWeekKey(today);
|
|
6599
|
+
const dayOfWeek = current.getDay();
|
|
6600
|
+
const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
|
6601
|
+
current.setDate(current.getDate() + daysToMonday);
|
|
6602
|
+
for (let i = 0; i < count; i++) {
|
|
6603
|
+
const weekStart = new Date(current);
|
|
6604
|
+
const weekEnd = new Date(current);
|
|
6605
|
+
weekEnd.setDate(weekEnd.getDate() + 6);
|
|
6606
|
+
const weekNumber = getISOWeek(weekStart);
|
|
6607
|
+
const year = weekStart.getFullYear();
|
|
6608
|
+
const weekKey = `${year}-W${weekNumber.toString().padStart(2, "0")}`;
|
|
6609
|
+
weeks.push({
|
|
6610
|
+
weekNumber,
|
|
6611
|
+
year,
|
|
6612
|
+
startDate: weekStart,
|
|
6613
|
+
endDate: weekEnd,
|
|
6614
|
+
label: `W${weekNumber.toString().padStart(2, "0")}`,
|
|
6615
|
+
dateRange: formatDateRange(weekStart, weekEnd),
|
|
6616
|
+
isCurrentWeek: weekKey === currentWeekKey
|
|
6617
|
+
});
|
|
6618
|
+
current.setDate(current.getDate() + 7);
|
|
6619
|
+
}
|
|
6620
|
+
return weeks;
|
|
6621
|
+
}
|
|
6622
|
+
function formatDateRange(start, end) {
|
|
6623
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
6624
|
+
const startMonth = months[start.getMonth()];
|
|
6625
|
+
const endMonth = months[end.getMonth()];
|
|
6626
|
+
if (startMonth === endMonth) {
|
|
6627
|
+
return `${startMonth} ${start.getDate()} - ${end.getDate()}`;
|
|
6628
|
+
}
|
|
6629
|
+
return `${startMonth} ${start.getDate()} - ${endMonth} ${end.getDate()}`;
|
|
6630
|
+
}
|
|
6631
|
+
function formatProductionUnit(unit) {
|
|
6632
|
+
const unitLabels = {
|
|
6633
|
+
quantity: "pcs",
|
|
6634
|
+
kvm: "m\xB2",
|
|
6635
|
+
ton: "ton",
|
|
6636
|
+
kg: "kg",
|
|
6637
|
+
m: "m",
|
|
6638
|
+
pcs: "pcs"
|
|
6639
|
+
};
|
|
6640
|
+
return unitLabels[unit] || unit;
|
|
6641
|
+
}
|
|
6642
|
+
function LocationIcon({ type }) {
|
|
6643
|
+
if (type === "production") {
|
|
6644
|
+
return /* @__PURE__ */ jsx(Factory, { className: "h-3 w-3" });
|
|
6645
|
+
}
|
|
6646
|
+
return /* @__PURE__ */ jsx(Truck, { className: "h-3 w-3" });
|
|
6647
|
+
}
|
|
6648
|
+
function PlanningWeekCommentPopover({
|
|
6649
|
+
comments,
|
|
6650
|
+
weekLabel,
|
|
6651
|
+
weekKey,
|
|
6652
|
+
locationOptions,
|
|
6653
|
+
onAddComment,
|
|
6654
|
+
onCommentClick,
|
|
6655
|
+
open,
|
|
6656
|
+
onOpenChange
|
|
6657
|
+
}) {
|
|
6658
|
+
const [newCommentText, setNewCommentText] = React22.useState("");
|
|
6659
|
+
const [selectedLocationId, setSelectedLocationId] = React22.useState("");
|
|
6660
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22.useState(true);
|
|
6661
|
+
const [showAddForm, setShowAddForm] = React22.useState(false);
|
|
6662
|
+
const selectedLocation = React22.useMemo(() => {
|
|
6663
|
+
return locationOptions.find((opt) => opt.id === selectedLocationId);
|
|
6664
|
+
}, [locationOptions, selectedLocationId]);
|
|
6665
|
+
const handleSubmit = () => {
|
|
6666
|
+
if (newCommentText.trim() && selectedLocation && onAddComment) {
|
|
6667
|
+
const location = {
|
|
6668
|
+
type: selectedLocation.type,
|
|
6669
|
+
weekKey,
|
|
6670
|
+
supplierId: selectedLocation.supplierId,
|
|
6671
|
+
supplierName: selectedLocation.supplierName,
|
|
6672
|
+
deliveryId: selectedLocation.deliveryId,
|
|
6673
|
+
deliveryLabel: selectedLocation.deliveryLabel
|
|
6674
|
+
};
|
|
6675
|
+
onAddComment(newCommentText.trim(), location);
|
|
6676
|
+
setNewCommentText("");
|
|
6677
|
+
setSelectedLocationId("");
|
|
6678
|
+
setShowAddForm(false);
|
|
6679
|
+
setViewCommentsOpen(true);
|
|
6680
|
+
}
|
|
6681
|
+
};
|
|
6682
|
+
const handleKeyDown = (e) => {
|
|
6683
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
6684
|
+
e.preventDefault();
|
|
6685
|
+
handleSubmit();
|
|
6686
|
+
}
|
|
6687
|
+
if (e.key === "Escape") {
|
|
6688
|
+
setShowAddForm(false);
|
|
6689
|
+
setSelectedLocationId("");
|
|
6690
|
+
setNewCommentText("");
|
|
6691
|
+
}
|
|
6692
|
+
};
|
|
6693
|
+
const handleCommentClick = (comment) => {
|
|
6694
|
+
if (comment.location && onCommentClick) {
|
|
6695
|
+
onCommentClick(comment);
|
|
6696
|
+
}
|
|
6697
|
+
};
|
|
6698
|
+
const formatDate2 = (date) => {
|
|
6699
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
6700
|
+
month: "short",
|
|
6701
|
+
day: "numeric",
|
|
6702
|
+
hour: "numeric",
|
|
6703
|
+
minute: "2-digit"
|
|
6704
|
+
}).format(date);
|
|
6705
|
+
};
|
|
6706
|
+
const prevOpenRef = React22.useRef(open);
|
|
6707
|
+
React22.useEffect(() => {
|
|
6708
|
+
const wasOpen = prevOpenRef.current;
|
|
6709
|
+
prevOpenRef.current = open;
|
|
6710
|
+
if (wasOpen && !open) {
|
|
6711
|
+
setShowAddForm(false);
|
|
6712
|
+
setNewCommentText("");
|
|
6713
|
+
setSelectedLocationId("");
|
|
6714
|
+
}
|
|
6715
|
+
}, [open]);
|
|
6716
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange, children: [
|
|
6717
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
6718
|
+
/* @__PURE__ */ jsxs(
|
|
6719
|
+
PopoverContent,
|
|
6720
|
+
{
|
|
6721
|
+
className: "w-80 p-0 z-[100]",
|
|
6722
|
+
align: "end",
|
|
6723
|
+
sideOffset: 8,
|
|
6724
|
+
collisionPadding: 16,
|
|
6725
|
+
children: [
|
|
6726
|
+
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
6727
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
6728
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: weekLabel })
|
|
6729
|
+
] }),
|
|
6730
|
+
/* @__PURE__ */ jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
6731
|
+
/* @__PURE__ */ jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
6732
|
+
/* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", className: "w-full justify-between h-8 px-2", children: [
|
|
6733
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [
|
|
6734
|
+
"Comments ",
|
|
6735
|
+
comments.length > 0 && `(${comments.length})`
|
|
6736
|
+
] }),
|
|
6737
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: cn(
|
|
6738
|
+
"h-4 w-4 transition-transform duration-200",
|
|
6739
|
+
viewCommentsOpen && "rotate-180"
|
|
6740
|
+
) })
|
|
6741
|
+
] }) }),
|
|
6742
|
+
/* @__PURE__ */ jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => {
|
|
6743
|
+
const hasLocation = !!comment.location;
|
|
6744
|
+
const locationLabel = comment.location ? getCommentLocationLabel(comment.location) : null;
|
|
6745
|
+
return /* @__PURE__ */ jsxs(
|
|
6746
|
+
"div",
|
|
6747
|
+
{
|
|
6748
|
+
className: cn(
|
|
6749
|
+
"rounded-lg bg-muted/50 p-3 space-y-2",
|
|
6750
|
+
hasLocation && "cursor-pointer hover:bg-muted/70 transition-colors"
|
|
6751
|
+
),
|
|
6752
|
+
onClick: () => handleCommentClick(comment),
|
|
6753
|
+
role: hasLocation ? "button" : void 0,
|
|
6754
|
+
tabIndex: hasLocation ? 0 : void 0,
|
|
6755
|
+
onKeyDown: hasLocation ? (e) => {
|
|
6756
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6757
|
+
e.preventDefault();
|
|
6758
|
+
handleCommentClick(comment);
|
|
6759
|
+
}
|
|
6760
|
+
} : void 0,
|
|
6761
|
+
children: [
|
|
6762
|
+
locationLabel && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6763
|
+
/* @__PURE__ */ jsxs(
|
|
6764
|
+
Badge,
|
|
6765
|
+
{
|
|
6766
|
+
variant: "outline",
|
|
6767
|
+
className: "text-[10px] px-2 py-0 h-5 font-medium bg-background gap-1",
|
|
6768
|
+
children: [
|
|
6769
|
+
/* @__PURE__ */ jsx(LocationIcon, { type: comment.location.type }),
|
|
6770
|
+
locationLabel
|
|
6771
|
+
]
|
|
6772
|
+
}
|
|
6773
|
+
),
|
|
6774
|
+
hasLocation && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-muted-foreground" })
|
|
6775
|
+
] }),
|
|
6776
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6777
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
6778
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
6779
|
+
] }),
|
|
6780
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
6781
|
+
]
|
|
6782
|
+
},
|
|
6783
|
+
comment.id
|
|
6784
|
+
);
|
|
6785
|
+
}) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
6786
|
+
] }),
|
|
6787
|
+
/* @__PURE__ */ jsx(Separator, { className: "my-2" }),
|
|
6788
|
+
!showAddForm ? /* @__PURE__ */ jsxs(
|
|
6789
|
+
Button,
|
|
6790
|
+
{
|
|
6791
|
+
variant: "outline",
|
|
6792
|
+
size: "sm",
|
|
6793
|
+
className: "w-full justify-center gap-2 h-8",
|
|
6794
|
+
onClick: () => setShowAddForm(true),
|
|
6795
|
+
disabled: locationOptions.length === 0,
|
|
6796
|
+
children: [
|
|
6797
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
|
|
6798
|
+
locationOptions.length === 0 ? "No suppliers available" : "Add comment"
|
|
6799
|
+
]
|
|
6800
|
+
}
|
|
6801
|
+
) : /* @__PURE__ */ jsxs("div", { className: cn(
|
|
6802
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
6803
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
6804
|
+
), children: [
|
|
6805
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
6806
|
+
/* @__PURE__ */ jsxs(Label2, { htmlFor: "supplier-prefix-select", className: "text-xs font-medium", children: [
|
|
6807
|
+
"Supplier / Prefix ",
|
|
6808
|
+
/* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
|
|
6809
|
+
] }),
|
|
6810
|
+
/* @__PURE__ */ jsxs(Select, { value: selectedLocationId, onValueChange: setSelectedLocationId, children: [
|
|
6811
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: "supplier-prefix-select", size: "sm", className: "w-full", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select supplier / prefix..." }) }),
|
|
6812
|
+
/* @__PURE__ */ jsx(SelectContent, { children: locationOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6813
|
+
/* @__PURE__ */ jsx(LocationIcon, { type: option.type }),
|
|
6814
|
+
/* @__PURE__ */ jsx("span", { children: option.label })
|
|
6815
|
+
] }) }, option.id)) })
|
|
6816
|
+
] })
|
|
6817
|
+
] }),
|
|
6818
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
6819
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "comment-text", className: "text-xs font-medium", children: "Comment" }),
|
|
6820
|
+
/* @__PURE__ */ jsx(
|
|
6821
|
+
Textarea,
|
|
6822
|
+
{
|
|
6823
|
+
id: "comment-text",
|
|
6824
|
+
placeholder: "Type your comment...",
|
|
6825
|
+
value: newCommentText,
|
|
6826
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
6827
|
+
onKeyDown: handleKeyDown,
|
|
6828
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
6829
|
+
autoFocus: true
|
|
6830
|
+
}
|
|
6831
|
+
)
|
|
6832
|
+
] }),
|
|
6833
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
6834
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
6835
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6836
|
+
/* @__PURE__ */ jsx(
|
|
6837
|
+
Button,
|
|
6838
|
+
{
|
|
6839
|
+
variant: "ghost",
|
|
6840
|
+
size: "sm",
|
|
6841
|
+
className: "h-7",
|
|
6842
|
+
onClick: () => {
|
|
6843
|
+
setShowAddForm(false);
|
|
6844
|
+
setNewCommentText("");
|
|
6845
|
+
setSelectedLocationId("");
|
|
6846
|
+
},
|
|
6847
|
+
children: "Cancel"
|
|
6848
|
+
}
|
|
6849
|
+
),
|
|
6850
|
+
/* @__PURE__ */ jsxs(
|
|
6851
|
+
Button,
|
|
6852
|
+
{
|
|
6853
|
+
size: "sm",
|
|
6854
|
+
className: "h-7 gap-1",
|
|
6855
|
+
onClick: handleSubmit,
|
|
6856
|
+
disabled: !newCommentText.trim() || !selectedLocationId,
|
|
6857
|
+
children: [
|
|
6858
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3 w-3" }),
|
|
6859
|
+
"Save"
|
|
6860
|
+
]
|
|
6861
|
+
}
|
|
6862
|
+
)
|
|
6863
|
+
] })
|
|
6864
|
+
] })
|
|
6865
|
+
] })
|
|
6866
|
+
] })
|
|
6867
|
+
]
|
|
6868
|
+
}
|
|
6869
|
+
)
|
|
6870
|
+
] });
|
|
6871
|
+
}
|
|
6872
|
+
function generateLocationOptions(suppliers, weekKey) {
|
|
6873
|
+
const options = [];
|
|
6874
|
+
for (const supplier of suppliers) {
|
|
6875
|
+
const weekData = supplier.weeks[weekKey];
|
|
6876
|
+
options.push({
|
|
6877
|
+
id: `${supplier.id}-production`,
|
|
6878
|
+
label: `${supplier.name} - Production`,
|
|
6879
|
+
type: "production",
|
|
6880
|
+
supplierId: supplier.id,
|
|
6881
|
+
supplierName: supplier.name
|
|
6882
|
+
});
|
|
6883
|
+
if (weekData?.deliveries) {
|
|
6884
|
+
for (const delivery of weekData.deliveries) {
|
|
6885
|
+
options.push({
|
|
6886
|
+
id: `${supplier.id}-delivery-${delivery.id}`,
|
|
6887
|
+
label: `${supplier.name} - ${delivery.label || `Delivery ${delivery.id}`}`,
|
|
6888
|
+
type: "delivery",
|
|
6889
|
+
supplierId: supplier.id,
|
|
6890
|
+
supplierName: supplier.name,
|
|
6891
|
+
deliveryId: delivery.id,
|
|
6892
|
+
deliveryLabel: delivery.label || `Delivery ${delivery.id}`
|
|
6893
|
+
});
|
|
6894
|
+
}
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
return options;
|
|
6898
|
+
}
|
|
6899
|
+
function WeekHeader({
|
|
6900
|
+
className,
|
|
6901
|
+
week,
|
|
6902
|
+
weekKey,
|
|
6903
|
+
comments = [],
|
|
6904
|
+
showCommentButton = true,
|
|
6905
|
+
locationOptions = [],
|
|
6906
|
+
onAddComment,
|
|
6907
|
+
onCommentClick,
|
|
6908
|
+
...props
|
|
6909
|
+
}) {
|
|
6910
|
+
return /* @__PURE__ */ jsxs(
|
|
6911
|
+
"div",
|
|
6912
|
+
{
|
|
6913
|
+
"data-slot": "week-header",
|
|
6914
|
+
"data-current-week": week.isCurrentWeek,
|
|
6915
|
+
className: cn(
|
|
6916
|
+
"flex items-center justify-between gap-2 min-w-[140px] text-left",
|
|
6917
|
+
className
|
|
6918
|
+
),
|
|
6919
|
+
...props,
|
|
6920
|
+
children: [
|
|
6921
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
6922
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6923
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
6924
|
+
"text-sm font-semibold tracking-tight",
|
|
6925
|
+
week.isCurrentWeek ? "text-primary" : "text-foreground"
|
|
6926
|
+
), children: week.label }),
|
|
6927
|
+
week.isCurrentWeek && /* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
6928
|
+
/* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75" }),
|
|
6929
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary" })
|
|
6930
|
+
] })
|
|
6931
|
+
] }),
|
|
6932
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-normal text-muted-foreground/60 whitespace-nowrap", children: week.dateRange })
|
|
6933
|
+
] }),
|
|
6934
|
+
showCommentButton && weekKey && /* @__PURE__ */ jsx(
|
|
6935
|
+
PlanningWeekCommentPopover,
|
|
6936
|
+
{
|
|
6937
|
+
comments,
|
|
6938
|
+
weekLabel: week.label,
|
|
6939
|
+
weekKey,
|
|
6940
|
+
locationOptions,
|
|
6941
|
+
onAddComment,
|
|
6942
|
+
onCommentClick
|
|
6943
|
+
}
|
|
6944
|
+
)
|
|
6945
|
+
]
|
|
6946
|
+
}
|
|
6947
|
+
);
|
|
6948
|
+
}
|
|
6949
|
+
function SupplierColumnHeader({
|
|
6950
|
+
column
|
|
6951
|
+
}) {
|
|
6952
|
+
return /* @__PURE__ */ jsxs(
|
|
6953
|
+
Button,
|
|
6954
|
+
{
|
|
6955
|
+
variant: "ghost",
|
|
6956
|
+
size: "sm",
|
|
6957
|
+
className: "-ml-3 h-8 data-[state=open]:bg-accent",
|
|
6958
|
+
onClick: () => column.toggleSorting(column.getIsSorted() === "asc"),
|
|
6959
|
+
children: [
|
|
6960
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Supplier / Scope" }),
|
|
6961
|
+
/* @__PURE__ */ jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })
|
|
6962
|
+
]
|
|
6963
|
+
}
|
|
6964
|
+
);
|
|
6965
|
+
}
|
|
6966
|
+
function getSupplierColumn() {
|
|
6967
|
+
return {
|
|
6968
|
+
id: "supplier",
|
|
6969
|
+
accessorKey: "name",
|
|
6970
|
+
header: ({ column }) => /* @__PURE__ */ jsx(SupplierColumnHeader, { column }),
|
|
6971
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(SupplierCell, { supplier: row.original }),
|
|
6972
|
+
enableSorting: true,
|
|
6973
|
+
enableHiding: false
|
|
6974
|
+
};
|
|
6975
|
+
}
|
|
6976
|
+
function WeekHeaderWithComments({
|
|
6977
|
+
week,
|
|
6978
|
+
weekKey,
|
|
6979
|
+
config,
|
|
6980
|
+
suppliers
|
|
6981
|
+
}) {
|
|
6982
|
+
const weekComments = config?.weekComments?.[weekKey] ?? [];
|
|
6983
|
+
let filteredSuppliers = suppliers;
|
|
6984
|
+
if (config?.userRole === "supplier" && config?.currentSupplierId) {
|
|
6985
|
+
filteredSuppliers = suppliers.filter((s) => s.id === config.currentSupplierId);
|
|
6986
|
+
}
|
|
6987
|
+
const locationOptions = generateLocationOptions(filteredSuppliers, weekKey);
|
|
6988
|
+
const handleAddComment = config?.onAddWeekComment ? (text, location) => {
|
|
6989
|
+
config.onAddWeekComment?.(weekKey, text, location);
|
|
6990
|
+
} : void 0;
|
|
6991
|
+
const handleCommentClick = config?.onCommentClick;
|
|
6992
|
+
return /* @__PURE__ */ jsx(
|
|
6993
|
+
WeekHeader,
|
|
6994
|
+
{
|
|
6995
|
+
week,
|
|
6996
|
+
weekKey,
|
|
6997
|
+
comments: weekComments,
|
|
6998
|
+
showCommentButton: true,
|
|
6999
|
+
locationOptions,
|
|
7000
|
+
onAddComment: handleAddComment,
|
|
7001
|
+
onCommentClick: handleCommentClick
|
|
7002
|
+
}
|
|
7003
|
+
);
|
|
7004
|
+
}
|
|
7005
|
+
function generateWeekColumns(weeks, config, suppliers) {
|
|
7006
|
+
return weeks.map((week) => {
|
|
7007
|
+
const weekKey = getWeekKey(week.startDate);
|
|
7008
|
+
return {
|
|
7009
|
+
id: weekKey,
|
|
7010
|
+
accessorFn: (supplier) => supplier.weeks[weekKey],
|
|
7011
|
+
header: () => /* @__PURE__ */ jsx(
|
|
7012
|
+
WeekHeaderWithComments,
|
|
7013
|
+
{
|
|
7014
|
+
week,
|
|
7015
|
+
weekKey,
|
|
7016
|
+
config,
|
|
7017
|
+
suppliers: suppliers ?? []
|
|
7018
|
+
}
|
|
7019
|
+
),
|
|
7020
|
+
cell: ({ row }) => {
|
|
7021
|
+
const supplier = row.original;
|
|
7022
|
+
const data = supplier.weeks[weekKey] || { type: "empty" };
|
|
7023
|
+
return /* @__PURE__ */ jsx(
|
|
7024
|
+
WeekCell,
|
|
7025
|
+
{
|
|
7026
|
+
data,
|
|
7027
|
+
week,
|
|
7028
|
+
supplier,
|
|
7029
|
+
isCurrentWeek: week.isCurrentWeek,
|
|
7030
|
+
onCellClick: config?.onCellClick ? () => config.onCellClick?.(supplier, week, data) : void 0
|
|
7031
|
+
}
|
|
7032
|
+
);
|
|
7033
|
+
},
|
|
7034
|
+
enableSorting: false,
|
|
7035
|
+
enableHiding: true
|
|
7036
|
+
};
|
|
7037
|
+
});
|
|
7038
|
+
}
|
|
7039
|
+
function generateColumns(weeks, config, suppliers) {
|
|
7040
|
+
return [
|
|
7041
|
+
getSupplierColumn(),
|
|
7042
|
+
...generateWeekColumns(weeks, config, suppliers)
|
|
7043
|
+
];
|
|
7044
|
+
}
|
|
7045
|
+
function PlanningTable({
|
|
7046
|
+
className,
|
|
7047
|
+
suppliers,
|
|
7048
|
+
config = {}
|
|
7049
|
+
}) {
|
|
7050
|
+
const {
|
|
7051
|
+
weekCount = 12,
|
|
7052
|
+
startDate = /* @__PURE__ */ new Date(),
|
|
7053
|
+
highlightCurrentWeek = true,
|
|
7054
|
+
showToolbar = true,
|
|
7055
|
+
showPagination = true,
|
|
7056
|
+
pageSizeOptions = [10, 20, 30, 50],
|
|
7057
|
+
defaultPageSize = 10,
|
|
7058
|
+
stickySupplierColumn = true,
|
|
7059
|
+
maxHeight = "600px"
|
|
7060
|
+
} = config;
|
|
7061
|
+
const weeks = React22.useMemo(
|
|
7062
|
+
() => generateWeeks(startDate, weekCount),
|
|
7063
|
+
[startDate, weekCount]
|
|
7064
|
+
);
|
|
7065
|
+
const currentWeekKey = React22.useMemo(() => {
|
|
7066
|
+
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
7067
|
+
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
7068
|
+
}, [weeks]);
|
|
7069
|
+
const columns = React22.useMemo(
|
|
7070
|
+
() => generateColumns(weeks, config, suppliers),
|
|
7071
|
+
[weeks, config, suppliers]
|
|
7072
|
+
);
|
|
7073
|
+
const [sorting, setSorting] = React22.useState([]);
|
|
7074
|
+
const [columnFilters, setColumnFilters] = React22.useState([]);
|
|
7075
|
+
const [columnVisibility, setColumnVisibility] = React22.useState({});
|
|
7076
|
+
const [rowSelection, setRowSelection] = React22.useState({});
|
|
7077
|
+
const table = useReactTable({
|
|
7078
|
+
data: suppliers,
|
|
7079
|
+
columns,
|
|
7080
|
+
getCoreRowModel: getCoreRowModel(),
|
|
7081
|
+
getSortedRowModel: getSortedRowModel(),
|
|
7082
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
7083
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
7084
|
+
onSortingChange: setSorting,
|
|
7085
|
+
onColumnFiltersChange: setColumnFilters,
|
|
7086
|
+
onColumnVisibilityChange: setColumnVisibility,
|
|
7087
|
+
onRowSelectionChange: setRowSelection,
|
|
7088
|
+
state: {
|
|
7089
|
+
sorting,
|
|
7090
|
+
columnFilters,
|
|
7091
|
+
columnVisibility,
|
|
7092
|
+
rowSelection
|
|
7093
|
+
},
|
|
7094
|
+
initialState: {
|
|
7095
|
+
pagination: {
|
|
7096
|
+
pageSize: defaultPageSize
|
|
7097
|
+
}
|
|
7098
|
+
}
|
|
7099
|
+
});
|
|
7100
|
+
return /* @__PURE__ */ jsxs(
|
|
7101
|
+
"div",
|
|
7102
|
+
{
|
|
7103
|
+
"data-slot": "planning-table",
|
|
7104
|
+
className: cn("flex flex-col gap-4", className),
|
|
7105
|
+
children: [
|
|
7106
|
+
showToolbar && /* @__PURE__ */ jsx(PlanningTableToolbar, { table }),
|
|
7107
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-xl border bg-background shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxs(
|
|
7108
|
+
ScrollArea,
|
|
7109
|
+
{
|
|
7110
|
+
className: "w-full",
|
|
7111
|
+
style: { maxHeight },
|
|
7112
|
+
children: [
|
|
7113
|
+
/* @__PURE__ */ jsxs("table", { className: "w-full border-collapse", children: [
|
|
7114
|
+
/* @__PURE__ */ jsx("thead", { className: "sticky top-0 z-20", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(
|
|
7115
|
+
"tr",
|
|
7116
|
+
{
|
|
7117
|
+
children: headerGroup.headers.map((header, index) => {
|
|
7118
|
+
const isCurrentWeekColumn = header.id === currentWeekKey;
|
|
7119
|
+
return /* @__PURE__ */ jsx(
|
|
7120
|
+
"th",
|
|
7121
|
+
{
|
|
7122
|
+
className: cn(
|
|
7123
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
7124
|
+
"border-r border-b border-border last:border-r-0 bg-sidebar",
|
|
7125
|
+
// First column: sticky with right-edge shadow (Quantum token)
|
|
7126
|
+
index === 0 && stickySupplierColumn && [
|
|
7127
|
+
"sticky left-0 z-30 min-w-[200px]",
|
|
7128
|
+
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7129
|
+
],
|
|
7130
|
+
index > 0 && "min-w-[140px]",
|
|
7131
|
+
// Current week: only highlight text/dot, not full background
|
|
7132
|
+
isCurrentWeekColumn && highlightCurrentWeek && "text-primary"
|
|
7133
|
+
),
|
|
7134
|
+
children: header.isPlaceholder ? null : flexRender(
|
|
7135
|
+
header.column.columnDef.header,
|
|
7136
|
+
header.getContext()
|
|
7137
|
+
)
|
|
7138
|
+
},
|
|
7139
|
+
header.id
|
|
7140
|
+
);
|
|
7141
|
+
})
|
|
7142
|
+
},
|
|
7143
|
+
headerGroup.id
|
|
7144
|
+
)) }),
|
|
7145
|
+
/* @__PURE__ */ jsx("tbody", { className: "bg-background", children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
|
|
7146
|
+
"tr",
|
|
7147
|
+
{
|
|
7148
|
+
"data-state": row.getIsSelected() && "selected",
|
|
7149
|
+
className: "border-b border-border last:border-b-0",
|
|
7150
|
+
children: row.getVisibleCells().map((cell, index) => {
|
|
7151
|
+
return /* @__PURE__ */ jsx(
|
|
7152
|
+
"td",
|
|
7153
|
+
{
|
|
7154
|
+
className: cn(
|
|
7155
|
+
"p-0 align-top border-r border-border last:border-r-0 bg-background",
|
|
7156
|
+
// First column: sticky WHITE with right-edge shadow (Quantum token)
|
|
7157
|
+
index === 0 && stickySupplierColumn && [
|
|
7158
|
+
"sticky left-0 z-10 min-w-[200px]",
|
|
7159
|
+
"shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
7160
|
+
],
|
|
7161
|
+
index > 0 && "min-w-[140px]"
|
|
7162
|
+
),
|
|
7163
|
+
children: flexRender(
|
|
7164
|
+
cell.column.columnDef.cell,
|
|
7165
|
+
cell.getContext()
|
|
7166
|
+
)
|
|
7167
|
+
},
|
|
7168
|
+
cell.id
|
|
7169
|
+
);
|
|
7170
|
+
})
|
|
7171
|
+
},
|
|
7172
|
+
row.id
|
|
7173
|
+
)) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
7174
|
+
"td",
|
|
7175
|
+
{
|
|
7176
|
+
colSpan: columns.length,
|
|
7177
|
+
className: "h-24 text-center text-muted-foreground bg-background",
|
|
7178
|
+
children: "No suppliers found."
|
|
7179
|
+
}
|
|
7180
|
+
) }) })
|
|
7181
|
+
] }),
|
|
7182
|
+
/* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" }),
|
|
7183
|
+
/* @__PURE__ */ jsx(ScrollBar, { orientation: "vertical" })
|
|
7184
|
+
]
|
|
7185
|
+
}
|
|
7186
|
+
) }),
|
|
7187
|
+
showPagination && /* @__PURE__ */ jsx(
|
|
7188
|
+
DataTablePagination,
|
|
7189
|
+
{
|
|
7190
|
+
table,
|
|
7191
|
+
showRowSelection: false,
|
|
7192
|
+
pageSizeOptions
|
|
7193
|
+
}
|
|
7194
|
+
)
|
|
7195
|
+
]
|
|
7196
|
+
}
|
|
7197
|
+
);
|
|
7198
|
+
}
|
|
7199
|
+
function getStatusBadgeVariant(status) {
|
|
7200
|
+
switch (status) {
|
|
7201
|
+
case "on-time":
|
|
7202
|
+
return "outline";
|
|
7203
|
+
case "delayed":
|
|
7204
|
+
return "secondary";
|
|
7205
|
+
case "critical":
|
|
7206
|
+
return "destructive";
|
|
7207
|
+
default:
|
|
7208
|
+
return "outline";
|
|
7209
|
+
}
|
|
7210
|
+
}
|
|
7211
|
+
function getStatusBadgeClasses(status) {
|
|
7212
|
+
switch (status) {
|
|
7213
|
+
case "on-time":
|
|
7214
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7215
|
+
case "delayed":
|
|
7216
|
+
return "border-amber-500 text-amber-600 bg-amber-50 dark:bg-amber-950/50";
|
|
7217
|
+
case "critical":
|
|
7218
|
+
return "";
|
|
7219
|
+
default:
|
|
7220
|
+
return "";
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
function getStatusLabel(status) {
|
|
7224
|
+
switch (status) {
|
|
7225
|
+
case "on-time":
|
|
7226
|
+
return "On Track";
|
|
7227
|
+
case "delayed":
|
|
7228
|
+
return "At Risk";
|
|
7229
|
+
case "critical":
|
|
7230
|
+
return "Critical";
|
|
7231
|
+
case "pending":
|
|
7232
|
+
return "Pending";
|
|
7233
|
+
default:
|
|
7234
|
+
return status;
|
|
7235
|
+
}
|
|
7236
|
+
}
|
|
7237
|
+
function getProgressVariant(status) {
|
|
7238
|
+
switch (status) {
|
|
7239
|
+
case "on-time":
|
|
7240
|
+
return "success";
|
|
7241
|
+
case "delayed":
|
|
7242
|
+
return "warning";
|
|
7243
|
+
case "critical":
|
|
7244
|
+
return "destructive";
|
|
7245
|
+
default:
|
|
7246
|
+
return "default";
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
function getShipmentStatusBadgeClasses(status) {
|
|
7250
|
+
switch (status) {
|
|
7251
|
+
case "sent":
|
|
7252
|
+
return "border-green-500 text-green-600 bg-green-50 dark:bg-green-950/50";
|
|
7253
|
+
case "not-sent":
|
|
7254
|
+
return "border-muted-foreground/50 text-muted-foreground bg-muted/50";
|
|
7255
|
+
case "moved":
|
|
7256
|
+
return "border-blue-500 text-blue-600 bg-blue-50 dark:bg-blue-950/50";
|
|
7257
|
+
case "addon":
|
|
7258
|
+
return "border-purple-500 text-purple-600 bg-purple-50 dark:bg-purple-950/50";
|
|
7259
|
+
case "planned":
|
|
7260
|
+
default:
|
|
7261
|
+
return "border-muted-foreground/50 text-muted-foreground";
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7264
|
+
function getShipmentStatusRowBg(status) {
|
|
7265
|
+
switch (status) {
|
|
7266
|
+
case "sent":
|
|
7267
|
+
return "bg-green-50/30 dark:bg-green-950/10";
|
|
7268
|
+
case "not-sent":
|
|
7269
|
+
return "bg-muted/30";
|
|
7270
|
+
case "moved":
|
|
7271
|
+
return "bg-blue-50/30 dark:bg-blue-950/10";
|
|
7272
|
+
case "addon":
|
|
7273
|
+
return "bg-purple-50/30 dark:bg-purple-950/10";
|
|
7274
|
+
default:
|
|
7275
|
+
return "";
|
|
7276
|
+
}
|
|
7277
|
+
}
|
|
7278
|
+
function DeliveryCommentPopover({
|
|
7279
|
+
comments = [],
|
|
7280
|
+
onAddComment,
|
|
7281
|
+
deliveryLabel
|
|
7282
|
+
}) {
|
|
7283
|
+
const [open, setOpen] = React22.useState(false);
|
|
7284
|
+
const [newCommentText, setNewCommentText] = React22.useState("");
|
|
7285
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22.useState(true);
|
|
7286
|
+
const [showAddForm, setShowAddForm] = React22.useState(false);
|
|
7287
|
+
const handleSubmit = () => {
|
|
7288
|
+
if (newCommentText.trim() && onAddComment) {
|
|
7289
|
+
onAddComment(newCommentText.trim());
|
|
7290
|
+
setNewCommentText("");
|
|
7291
|
+
setShowAddForm(false);
|
|
7292
|
+
setViewCommentsOpen(true);
|
|
7293
|
+
}
|
|
7294
|
+
};
|
|
7295
|
+
const handleKeyDown = (e) => {
|
|
7296
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
7297
|
+
e.preventDefault();
|
|
7298
|
+
handleSubmit();
|
|
7299
|
+
}
|
|
7300
|
+
if (e.key === "Escape") {
|
|
7301
|
+
setShowAddForm(false);
|
|
7302
|
+
setNewCommentText("");
|
|
7303
|
+
}
|
|
7304
|
+
};
|
|
7305
|
+
const formatDate2 = (date) => {
|
|
7306
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
7307
|
+
month: "short",
|
|
7308
|
+
day: "numeric",
|
|
7309
|
+
hour: "numeric",
|
|
7310
|
+
minute: "2-digit"
|
|
7311
|
+
}).format(date);
|
|
7312
|
+
};
|
|
7313
|
+
const prevOpenRef = React22.useRef(open);
|
|
7314
|
+
React22.useEffect(() => {
|
|
7315
|
+
const wasOpen = prevOpenRef.current;
|
|
7316
|
+
prevOpenRef.current = open;
|
|
7317
|
+
if (wasOpen && !open) {
|
|
7318
|
+
setShowAddForm(false);
|
|
7319
|
+
setNewCommentText("");
|
|
7320
|
+
}
|
|
7321
|
+
}, [open]);
|
|
7322
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
7323
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(CommentButton, { size: "sm", commentCount: comments.length }) }),
|
|
7324
|
+
/* @__PURE__ */ jsxs(
|
|
7325
|
+
PopoverContent,
|
|
7326
|
+
{
|
|
7327
|
+
className: "w-80 p-0 z-[100]",
|
|
7328
|
+
align: "end",
|
|
7329
|
+
sideOffset: 8,
|
|
7330
|
+
collisionPadding: 16,
|
|
7331
|
+
children: [
|
|
7332
|
+
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
7333
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
7334
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: deliveryLabel })
|
|
7335
|
+
] }),
|
|
7336
|
+
/* @__PURE__ */ jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
7337
|
+
/* @__PURE__ */ jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
7338
|
+
/* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", className: "w-full justify-between h-8 px-2", children: [
|
|
7339
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [
|
|
7340
|
+
"Comments ",
|
|
7341
|
+
comments.length > 0 && `(${comments.length})`
|
|
7342
|
+
] }),
|
|
7343
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: cn(
|
|
7344
|
+
"h-4 w-4 transition-transform duration-200",
|
|
7345
|
+
viewCommentsOpen && "rotate-180"
|
|
7346
|
+
) })
|
|
7347
|
+
] }) }),
|
|
7348
|
+
/* @__PURE__ */ jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted/50 p-3 space-y-2", children: [
|
|
7349
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7350
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7351
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
7352
|
+
] }),
|
|
7353
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7354
|
+
] }, comment.id)) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
7355
|
+
] }),
|
|
7356
|
+
/* @__PURE__ */ jsx(Separator, { className: "my-2" }),
|
|
7357
|
+
!showAddForm ? /* @__PURE__ */ jsxs(
|
|
7358
|
+
Button,
|
|
7359
|
+
{
|
|
7360
|
+
variant: "outline",
|
|
7361
|
+
size: "sm",
|
|
7362
|
+
className: "w-full justify-center gap-2 h-8",
|
|
7363
|
+
onClick: () => setShowAddForm(true),
|
|
7364
|
+
children: [
|
|
7365
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
|
|
7366
|
+
"Add comment"
|
|
7367
|
+
]
|
|
7368
|
+
}
|
|
7369
|
+
) : /* @__PURE__ */ jsxs("div", { className: cn(
|
|
7370
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
7371
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
7372
|
+
), children: [
|
|
7373
|
+
/* @__PURE__ */ jsx(
|
|
7374
|
+
Textarea,
|
|
7375
|
+
{
|
|
7376
|
+
placeholder: "Type your comment...",
|
|
7377
|
+
value: newCommentText,
|
|
7378
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
7379
|
+
onKeyDown: handleKeyDown,
|
|
7380
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
7381
|
+
autoFocus: true
|
|
7382
|
+
}
|
|
7383
|
+
),
|
|
7384
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7385
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
7386
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7387
|
+
/* @__PURE__ */ jsx(
|
|
7388
|
+
Button,
|
|
7389
|
+
{
|
|
7390
|
+
variant: "ghost",
|
|
7391
|
+
size: "sm",
|
|
7392
|
+
className: "h-7",
|
|
7393
|
+
onClick: () => {
|
|
7394
|
+
setShowAddForm(false);
|
|
7395
|
+
setNewCommentText("");
|
|
7396
|
+
},
|
|
7397
|
+
children: "Cancel"
|
|
7398
|
+
}
|
|
7399
|
+
),
|
|
7400
|
+
/* @__PURE__ */ jsxs(
|
|
7401
|
+
Button,
|
|
7402
|
+
{
|
|
7403
|
+
size: "sm",
|
|
7404
|
+
className: "h-7 gap-1",
|
|
7405
|
+
onClick: handleSubmit,
|
|
7406
|
+
disabled: !newCommentText.trim(),
|
|
7407
|
+
children: [
|
|
7408
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3 w-3" }),
|
|
7409
|
+
"Save"
|
|
7410
|
+
]
|
|
7411
|
+
}
|
|
7412
|
+
)
|
|
7413
|
+
] })
|
|
7414
|
+
] })
|
|
7415
|
+
] })
|
|
7416
|
+
] })
|
|
7417
|
+
]
|
|
7418
|
+
}
|
|
7419
|
+
)
|
|
7420
|
+
] });
|
|
7421
|
+
}
|
|
7422
|
+
function ProductionCommentSection({
|
|
7423
|
+
comments = [],
|
|
7424
|
+
onAddComment
|
|
7425
|
+
}) {
|
|
7426
|
+
const [showAddForm, setShowAddForm] = React22.useState(false);
|
|
7427
|
+
const [newComment, setNewComment] = React22.useState("");
|
|
7428
|
+
const handleSubmit = () => {
|
|
7429
|
+
if (newComment.trim() && onAddComment) {
|
|
7430
|
+
onAddComment(newComment.trim());
|
|
7431
|
+
setNewComment("");
|
|
7432
|
+
setShowAddForm(false);
|
|
7433
|
+
}
|
|
7434
|
+
};
|
|
7435
|
+
const handleKeyDown = (e) => {
|
|
7436
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
7437
|
+
e.preventDefault();
|
|
7438
|
+
handleSubmit();
|
|
7439
|
+
}
|
|
7440
|
+
if (e.key === "Escape") {
|
|
7441
|
+
setShowAddForm(false);
|
|
7442
|
+
setNewComment("");
|
|
7443
|
+
}
|
|
7444
|
+
};
|
|
7445
|
+
const formatDate2 = (date) => {
|
|
7446
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
7447
|
+
month: "short",
|
|
7448
|
+
day: "numeric",
|
|
7449
|
+
hour: "numeric",
|
|
7450
|
+
minute: "2-digit"
|
|
7451
|
+
}).format(date);
|
|
7452
|
+
};
|
|
7453
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
7454
|
+
comments.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-2", children: comments.map((comment) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted/50 p-2.5 space-y-1", children: [
|
|
7455
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7456
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
7457
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
7458
|
+
] }),
|
|
7459
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
7460
|
+
] }, comment.id)) }),
|
|
7461
|
+
!showAddForm ? /* @__PURE__ */ jsxs(
|
|
7462
|
+
Button,
|
|
7463
|
+
{
|
|
7464
|
+
variant: "ghost",
|
|
7465
|
+
size: "sm",
|
|
7466
|
+
className: "w-full justify-start gap-2 h-8 text-muted-foreground",
|
|
7467
|
+
onClick: () => setShowAddForm(true),
|
|
7468
|
+
children: [
|
|
7469
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: "h-3.5 w-3.5" }),
|
|
7470
|
+
comments.length > 0 ? "Add another comment" : "Add a comment..."
|
|
7471
|
+
]
|
|
7472
|
+
}
|
|
7473
|
+
) : /* @__PURE__ */ jsxs("div", { className: "space-y-2 animate-in fade-in-0 slide-in-from-top-2 duration-200", children: [
|
|
7474
|
+
/* @__PURE__ */ jsx(
|
|
7475
|
+
Textarea,
|
|
7476
|
+
{
|
|
7477
|
+
placeholder: "Add a comment...",
|
|
7478
|
+
value: newComment,
|
|
7479
|
+
onChange: (e) => setNewComment(e.target.value),
|
|
7480
|
+
onKeyDown: handleKeyDown,
|
|
7481
|
+
className: "min-h-[60px] text-sm resize-none",
|
|
7482
|
+
autoFocus: true
|
|
7483
|
+
}
|
|
7484
|
+
),
|
|
7485
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7486
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send" }),
|
|
7487
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7488
|
+
/* @__PURE__ */ jsx(
|
|
7489
|
+
Button,
|
|
7490
|
+
{
|
|
7491
|
+
variant: "ghost",
|
|
7492
|
+
size: "sm",
|
|
7493
|
+
className: "h-7",
|
|
7494
|
+
onClick: () => {
|
|
7495
|
+
setShowAddForm(false);
|
|
7496
|
+
setNewComment("");
|
|
7497
|
+
},
|
|
7498
|
+
children: "Cancel"
|
|
7499
|
+
}
|
|
7500
|
+
),
|
|
7501
|
+
/* @__PURE__ */ jsxs(
|
|
7502
|
+
Button,
|
|
7503
|
+
{
|
|
7504
|
+
size: "sm",
|
|
7505
|
+
className: "h-7 gap-1",
|
|
7506
|
+
onClick: handleSubmit,
|
|
7507
|
+
disabled: !newComment.trim(),
|
|
7508
|
+
children: [
|
|
7509
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3 w-3" }),
|
|
7510
|
+
"Save"
|
|
7511
|
+
]
|
|
7512
|
+
}
|
|
7513
|
+
)
|
|
7514
|
+
] })
|
|
7515
|
+
] })
|
|
7516
|
+
] })
|
|
7517
|
+
] });
|
|
7518
|
+
}
|
|
7519
|
+
function DeliveryListItem({
|
|
7520
|
+
delivery,
|
|
7521
|
+
index,
|
|
7522
|
+
onClick
|
|
7523
|
+
}) {
|
|
7524
|
+
const hasComments = (delivery.comments?.length ?? 0) > 0;
|
|
7525
|
+
return /* @__PURE__ */ jsxs(
|
|
7526
|
+
"button",
|
|
7527
|
+
{
|
|
7528
|
+
onClick,
|
|
7529
|
+
className: cn(
|
|
7530
|
+
"w-full flex items-center justify-between p-3 rounded-lg",
|
|
7531
|
+
"bg-card border hover:bg-muted/50 transition-colors cursor-pointer",
|
|
7532
|
+
"text-left"
|
|
7533
|
+
),
|
|
7534
|
+
children: [
|
|
7535
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7536
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
7537
|
+
"flex items-center justify-center h-8 w-8 rounded-lg",
|
|
7538
|
+
delivery.status === "on-time" && "bg-green-100 dark:bg-green-950/50",
|
|
7539
|
+
delivery.status === "delayed" && "bg-amber-100 dark:bg-amber-950/50",
|
|
7540
|
+
delivery.status === "critical" && "bg-red-100 dark:bg-red-950/50"
|
|
7541
|
+
), children: /* @__PURE__ */ jsx(Truck, { className: cn(
|
|
7542
|
+
"h-4 w-4",
|
|
7543
|
+
delivery.status === "on-time" && "text-green-600 dark:text-green-400",
|
|
7544
|
+
delivery.status === "delayed" && "text-amber-600 dark:text-amber-400",
|
|
7545
|
+
delivery.status === "critical" && "text-red-600 dark:text-red-400"
|
|
7546
|
+
) }) }),
|
|
7547
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7548
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7549
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: delivery.label || `Delivery ${index + 1}` }),
|
|
7550
|
+
hasComments && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
7551
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: "h-3 w-3 text-muted-foreground" }),
|
|
7552
|
+
/* @__PURE__ */ jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-primary" })
|
|
7553
|
+
] })
|
|
7554
|
+
] }),
|
|
7555
|
+
delivery.destination && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
7556
|
+
"\u2192 ",
|
|
7557
|
+
delivery.destination
|
|
7558
|
+
] })
|
|
7559
|
+
] })
|
|
7560
|
+
] }),
|
|
7561
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7562
|
+
/* @__PURE__ */ jsx(
|
|
7563
|
+
Badge,
|
|
7564
|
+
{
|
|
7565
|
+
variant: getStatusBadgeVariant(delivery.status),
|
|
7566
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7567
|
+
children: getStatusLabel(delivery.status)
|
|
7568
|
+
}
|
|
7569
|
+
),
|
|
7570
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
7571
|
+
] })
|
|
7572
|
+
]
|
|
7573
|
+
}
|
|
7574
|
+
);
|
|
7575
|
+
}
|
|
7576
|
+
function DeliveryDetailsView({
|
|
7577
|
+
delivery,
|
|
7578
|
+
week,
|
|
7579
|
+
onBack,
|
|
7580
|
+
onAddComment
|
|
7581
|
+
}) {
|
|
7582
|
+
const elements = delivery.elements ?? [];
|
|
7583
|
+
const categorizedElements = React22.useMemo(() => {
|
|
7584
|
+
const sent = [];
|
|
7585
|
+
const notSent = [];
|
|
7586
|
+
const moved = [];
|
|
7587
|
+
const addons = [];
|
|
7588
|
+
elements.forEach((element) => {
|
|
7589
|
+
const status = getElementShipmentStatus(element, delivery.id);
|
|
7590
|
+
switch (status) {
|
|
7591
|
+
case "sent":
|
|
7592
|
+
sent.push(element);
|
|
7593
|
+
break;
|
|
7594
|
+
case "not-sent":
|
|
7595
|
+
notSent.push(element);
|
|
7596
|
+
break;
|
|
7597
|
+
case "moved":
|
|
7598
|
+
moved.push(element);
|
|
7599
|
+
break;
|
|
7600
|
+
case "addon":
|
|
7601
|
+
addons.push(element);
|
|
7602
|
+
break;
|
|
7603
|
+
default:
|
|
7604
|
+
notSent.push(element);
|
|
7605
|
+
}
|
|
7606
|
+
});
|
|
7607
|
+
return { sent, notSent, moved, addons };
|
|
7608
|
+
}, [elements, delivery.id]);
|
|
7609
|
+
const totalCount = elements.length;
|
|
7610
|
+
const sentCount = categorizedElements.sent.length;
|
|
7611
|
+
(delivery.comments?.length ?? 0) > 0;
|
|
7612
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full animate-in slide-in-from-right-4 duration-200", children: [
|
|
7613
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 px-6 py-3 border-b", children: /* @__PURE__ */ jsxs(
|
|
7614
|
+
Button,
|
|
7615
|
+
{
|
|
7616
|
+
variant: "ghost",
|
|
7617
|
+
size: "sm",
|
|
7618
|
+
className: "gap-1 -ml-2",
|
|
7619
|
+
onClick: onBack,
|
|
7620
|
+
children: [
|
|
7621
|
+
/* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
|
|
7622
|
+
"Back"
|
|
7623
|
+
]
|
|
7624
|
+
}
|
|
7625
|
+
) }),
|
|
7626
|
+
/* @__PURE__ */ jsxs("div", { className: "px-6 py-4 space-y-2", children: [
|
|
7627
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
7628
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: delivery.label || "Delivery Details" }),
|
|
7629
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7630
|
+
/* @__PURE__ */ jsx(
|
|
7631
|
+
DeliveryCommentPopover,
|
|
7632
|
+
{
|
|
7633
|
+
comments: delivery.comments,
|
|
7634
|
+
onAddComment,
|
|
7635
|
+
deliveryLabel: delivery.label || "Delivery"
|
|
7636
|
+
}
|
|
7637
|
+
),
|
|
7638
|
+
/* @__PURE__ */ jsx(
|
|
7639
|
+
Badge,
|
|
7640
|
+
{
|
|
7641
|
+
variant: getStatusBadgeVariant(delivery.status),
|
|
7642
|
+
className: cn("text-xs", getStatusBadgeClasses(delivery.status)),
|
|
7643
|
+
children: getStatusLabel(delivery.status)
|
|
7644
|
+
}
|
|
7645
|
+
)
|
|
7646
|
+
] })
|
|
7647
|
+
] }),
|
|
7648
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
|
|
7649
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
7650
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "h-3.5 w-3.5" }),
|
|
7651
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7652
|
+
week.label,
|
|
7653
|
+
" \u2022 ",
|
|
7654
|
+
week.dateRange
|
|
7655
|
+
] })
|
|
7656
|
+
] }),
|
|
7657
|
+
delivery.destination && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
7658
|
+
/* @__PURE__ */ jsx(Truck, { className: "h-3.5 w-3.5" }),
|
|
7659
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7660
|
+
"\u2192 ",
|
|
7661
|
+
delivery.destination
|
|
7662
|
+
] })
|
|
7663
|
+
] })
|
|
7664
|
+
] })
|
|
7665
|
+
] }),
|
|
7666
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1 px-6 pb-6", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
7667
|
+
totalCount > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted/50 p-4", children: [
|
|
7668
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
7669
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Shipment Progress" }),
|
|
7670
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-semibold tabular-nums", children: [
|
|
7671
|
+
"Shipped ",
|
|
7672
|
+
sentCount,
|
|
7673
|
+
" / ",
|
|
7674
|
+
totalCount
|
|
7675
|
+
] })
|
|
7676
|
+
] }),
|
|
7677
|
+
/* @__PURE__ */ jsx("div", { className: "h-2 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
7678
|
+
"div",
|
|
7679
|
+
{
|
|
7680
|
+
className: cn(
|
|
7681
|
+
"h-full rounded-full transition-all",
|
|
7682
|
+
sentCount === totalCount ? "bg-green-500" : "bg-primary"
|
|
7683
|
+
),
|
|
7684
|
+
style: { width: `${totalCount > 0 ? sentCount / totalCount * 100 : 0}%` }
|
|
7685
|
+
}
|
|
7686
|
+
) }),
|
|
7687
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mt-3 flex-wrap", children: [
|
|
7688
|
+
categorizedElements.sent.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7689
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "h-3 w-3 text-green-600" }),
|
|
7690
|
+
/* @__PURE__ */ jsxs("span", { className: "text-green-700 dark:text-green-300", children: [
|
|
7691
|
+
categorizedElements.sent.length,
|
|
7692
|
+
" Sent"
|
|
7693
|
+
] })
|
|
7694
|
+
] }),
|
|
7695
|
+
categorizedElements.notSent.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7696
|
+
/* @__PURE__ */ jsx(XCircle, { className: "h-3 w-3 text-amber-600" }),
|
|
7697
|
+
/* @__PURE__ */ jsxs("span", { className: "text-amber-700 dark:text-amber-300", children: [
|
|
7698
|
+
categorizedElements.notSent.length,
|
|
7699
|
+
" Not sent"
|
|
7700
|
+
] })
|
|
7701
|
+
] }),
|
|
7702
|
+
categorizedElements.moved.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7703
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-3 w-3 text-blue-600" }),
|
|
7704
|
+
/* @__PURE__ */ jsxs("span", { className: "text-blue-700 dark:text-blue-300", children: [
|
|
7705
|
+
categorizedElements.moved.length,
|
|
7706
|
+
" Moved"
|
|
7707
|
+
] })
|
|
7708
|
+
] }),
|
|
7709
|
+
categorizedElements.addons.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
7710
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-3 w-3 text-purple-600" }),
|
|
7711
|
+
/* @__PURE__ */ jsxs("span", { className: "text-purple-700 dark:text-purple-300", children: [
|
|
7712
|
+
categorizedElements.addons.length,
|
|
7713
|
+
" Add-on"
|
|
7714
|
+
] })
|
|
7715
|
+
] })
|
|
7716
|
+
] })
|
|
7717
|
+
] }),
|
|
7718
|
+
elements.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
7719
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Elements" }),
|
|
7720
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border overflow-hidden", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
7721
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { className: "bg-sidebar hover:bg-sidebar", children: [
|
|
7722
|
+
/* @__PURE__ */ jsx(TableHead, { className: "font-semibold", children: "Prefix" }),
|
|
7723
|
+
/* @__PURE__ */ jsx(TableHead, { className: "font-semibold", children: "Type" }),
|
|
7724
|
+
/* @__PURE__ */ jsx(TableHead, { className: "font-semibold text-right", children: "Weight" }),
|
|
7725
|
+
/* @__PURE__ */ jsx(TableHead, { className: "font-semibold text-right", children: "Size (m\xB2)" }),
|
|
7726
|
+
/* @__PURE__ */ jsx(TableHead, { className: "font-semibold text-center", children: "Status" })
|
|
7727
|
+
] }) }),
|
|
7728
|
+
/* @__PURE__ */ jsx(TableBody, { children: elements.map((element) => {
|
|
7729
|
+
const shipmentStatus = getElementShipmentStatus(element, delivery.id);
|
|
7730
|
+
const statusLabel = getShipmentStatusLabel(shipmentStatus);
|
|
7731
|
+
return /* @__PURE__ */ jsxs(
|
|
7732
|
+
TableRow,
|
|
7733
|
+
{
|
|
7734
|
+
className: getShipmentStatusRowBg(shipmentStatus),
|
|
7735
|
+
children: [
|
|
7736
|
+
/* @__PURE__ */ jsx(TableCell, { className: "font-medium", children: element.prefix || "\u2014" }),
|
|
7737
|
+
/* @__PURE__ */ jsx(TableCell, { children: element.type || element.name || "\u2014" }),
|
|
7738
|
+
/* @__PURE__ */ jsx(TableCell, { className: "text-right tabular-nums", children: element.weight ? /* @__PURE__ */ jsxs("span", { children: [
|
|
7739
|
+
element.weight,
|
|
7740
|
+
" ",
|
|
7741
|
+
element.weightUnit || "kg"
|
|
7742
|
+
] }) : "\u2014" }),
|
|
7743
|
+
/* @__PURE__ */ jsx(TableCell, { className: "text-right tabular-nums", children: element.sizeSqm ? /* @__PURE__ */ jsx("span", { children: element.sizeSqm }) : "\u2014" }),
|
|
7744
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
7745
|
+
/* @__PURE__ */ jsx(
|
|
7746
|
+
Badge,
|
|
7747
|
+
{
|
|
7748
|
+
variant: "outline",
|
|
7749
|
+
className: cn(
|
|
7750
|
+
"text-[10px] h-5",
|
|
7751
|
+
getShipmentStatusBadgeClasses(shipmentStatus)
|
|
7752
|
+
),
|
|
7753
|
+
children: statusLabel
|
|
7754
|
+
}
|
|
7755
|
+
),
|
|
7756
|
+
shipmentStatus === "moved" && element.actualDeliveryLabel && /* @__PURE__ */ jsxs("span", { className: "text-[9px] text-blue-600 dark:text-blue-400", children: [
|
|
7757
|
+
"\u2192 ",
|
|
7758
|
+
element.actualDeliveryLabel
|
|
7759
|
+
] }),
|
|
7760
|
+
shipmentStatus === "addon" && element.originalDeliveryLabel && /* @__PURE__ */ jsxs("span", { className: "text-[9px] text-purple-600 dark:text-purple-400", children: [
|
|
7761
|
+
"from ",
|
|
7762
|
+
element.originalDeliveryLabel
|
|
7763
|
+
] })
|
|
7764
|
+
] }) })
|
|
7765
|
+
]
|
|
7766
|
+
},
|
|
7767
|
+
element.id
|
|
7768
|
+
);
|
|
7769
|
+
}) })
|
|
7770
|
+
] }) })
|
|
7771
|
+
] }),
|
|
7772
|
+
elements.length === 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
7773
|
+
/* @__PURE__ */ jsx(Package, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
|
|
7774
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No elements in this delivery" })
|
|
7775
|
+
] })
|
|
7776
|
+
] }) })
|
|
7777
|
+
] });
|
|
7778
|
+
}
|
|
7779
|
+
function MainView({
|
|
7780
|
+
supplier,
|
|
7781
|
+
week,
|
|
7782
|
+
data,
|
|
7783
|
+
producedValue,
|
|
7784
|
+
hasChanges,
|
|
7785
|
+
onProducedChange,
|
|
7786
|
+
onSave,
|
|
7787
|
+
onSelectDelivery,
|
|
7788
|
+
onAddProductionComment
|
|
7789
|
+
}) {
|
|
7790
|
+
const production = data?.production;
|
|
7791
|
+
const productionProgress = production ? Math.min(100, Math.round(production.produced / production.target * 100)) : data?.progress ?? 0;
|
|
7792
|
+
const productionStatus = production?.status ?? "on-time";
|
|
7793
|
+
const isComplete = productionProgress >= 100;
|
|
7794
|
+
const hasProductionComments = (production?.comments?.length ?? 0) > 0;
|
|
7795
|
+
return /* @__PURE__ */ jsxs("div", { className: "animate-in fade-in-0 duration-200", children: [
|
|
7796
|
+
/* @__PURE__ */ jsxs(DialogHeader, { className: "px-6 pt-6 pb-4", children: [
|
|
7797
|
+
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
7798
|
+
supplier.name,
|
|
7799
|
+
/* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs font-normal", children: supplier.badgeType })
|
|
7800
|
+
] }),
|
|
7801
|
+
/* @__PURE__ */ jsxs(DialogDescription, { className: "flex items-center gap-2", children: [
|
|
7802
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "h-4 w-4" }),
|
|
7803
|
+
week.label,
|
|
7804
|
+
" \u2022 ",
|
|
7805
|
+
week.dateRange
|
|
7806
|
+
] })
|
|
7807
|
+
] }),
|
|
7808
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1 px-6 pb-6", children: /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
|
|
7809
|
+
data.type !== "empty" && /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
|
|
7810
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7811
|
+
/* @__PURE__ */ jsx(Factory, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7812
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: "Production" }),
|
|
7813
|
+
/* @__PURE__ */ jsx(
|
|
7814
|
+
Badge,
|
|
7815
|
+
{
|
|
7816
|
+
variant: getStatusBadgeVariant(productionStatus),
|
|
7817
|
+
className: cn("text-xs ml-auto", getStatusBadgeClasses(productionStatus)),
|
|
7818
|
+
children: getStatusLabel(productionStatus)
|
|
7819
|
+
}
|
|
7820
|
+
)
|
|
7821
|
+
] }),
|
|
7822
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-6", children: [
|
|
7823
|
+
/* @__PURE__ */ jsx(
|
|
7824
|
+
CircularProgress,
|
|
7825
|
+
{
|
|
7826
|
+
value: productionProgress,
|
|
7827
|
+
size: 100,
|
|
7828
|
+
strokeWidth: 10,
|
|
7829
|
+
variant: getProgressVariant(productionStatus),
|
|
7830
|
+
showCheckmark: isComplete,
|
|
7831
|
+
children: isComplete ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7832
|
+
/* @__PURE__ */ jsx(Check, { className: "h-6 w-6 text-green-600" }),
|
|
7833
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-semibold text-green-600", children: [
|
|
7834
|
+
production?.produced ?? 0,
|
|
7835
|
+
" ",
|
|
7836
|
+
production ? formatProductionUnit(production.unit) : ""
|
|
7837
|
+
] })
|
|
7838
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
7839
|
+
/* @__PURE__ */ jsx("span", { className: "text-lg font-bold tabular-nums", children: production?.produced ?? 0 }),
|
|
7840
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
7841
|
+
"/ ",
|
|
7842
|
+
production?.target ?? 0,
|
|
7843
|
+
" ",
|
|
7844
|
+
production ? formatProductionUnit(production.unit) : ""
|
|
7845
|
+
] })
|
|
7846
|
+
] })
|
|
7847
|
+
}
|
|
7848
|
+
),
|
|
7849
|
+
production && /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
7850
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
7851
|
+
/* @__PURE__ */ jsxs(Label2, { htmlFor: "produced", className: "text-xs", children: [
|
|
7852
|
+
"Produced Amount (",
|
|
7853
|
+
formatProductionUnit(production.unit),
|
|
7854
|
+
")"
|
|
7855
|
+
] }),
|
|
7856
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
7857
|
+
Input,
|
|
7858
|
+
{
|
|
7859
|
+
id: "produced",
|
|
7860
|
+
type: "number",
|
|
7861
|
+
min: "0",
|
|
7862
|
+
max: production.target * 2,
|
|
7863
|
+
value: producedValue,
|
|
7864
|
+
onChange: onProducedChange,
|
|
7865
|
+
className: "h-9"
|
|
7866
|
+
}
|
|
7867
|
+
) }),
|
|
7868
|
+
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
|
|
7869
|
+
"Target: ",
|
|
7870
|
+
production.target,
|
|
7871
|
+
" ",
|
|
7872
|
+
formatProductionUnit(production.unit)
|
|
7873
|
+
] })
|
|
7874
|
+
] }),
|
|
7875
|
+
/* @__PURE__ */ jsx(
|
|
7876
|
+
Button,
|
|
7877
|
+
{
|
|
7878
|
+
size: "sm",
|
|
7879
|
+
className: "w-full",
|
|
7880
|
+
disabled: !hasChanges,
|
|
7881
|
+
onClick: onSave,
|
|
7882
|
+
children: hasChanges ? "Save Progress" : "No Changes"
|
|
7883
|
+
}
|
|
7884
|
+
)
|
|
7885
|
+
] })
|
|
7886
|
+
] }),
|
|
7887
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
7888
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7889
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Comments" }),
|
|
7890
|
+
hasProductionComments && /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
7891
|
+
"(",
|
|
7892
|
+
production?.comments?.length,
|
|
7893
|
+
")"
|
|
7894
|
+
] })
|
|
7895
|
+
] }),
|
|
7896
|
+
/* @__PURE__ */ jsx(
|
|
7897
|
+
ProductionCommentSection,
|
|
7898
|
+
{
|
|
7899
|
+
comments: production?.comments,
|
|
7900
|
+
onAddComment: onAddProductionComment
|
|
7901
|
+
}
|
|
7902
|
+
)
|
|
7903
|
+
] })
|
|
7904
|
+
] }),
|
|
7905
|
+
data.deliveries && data.deliveries.length > 0 && /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
|
|
7906
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7907
|
+
/* @__PURE__ */ jsx(Truck, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7908
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: "Deliveries" }),
|
|
7909
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground ml-auto", children: [
|
|
7910
|
+
data.deliveries.length,
|
|
7911
|
+
" scheduled"
|
|
7912
|
+
] })
|
|
7913
|
+
] }),
|
|
7914
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: data.deliveries.map((delivery, index) => /* @__PURE__ */ jsx(
|
|
7915
|
+
DeliveryListItem,
|
|
7916
|
+
{
|
|
7917
|
+
delivery,
|
|
7918
|
+
index,
|
|
7919
|
+
onClick: () => onSelectDelivery(delivery)
|
|
7920
|
+
},
|
|
7921
|
+
delivery.id
|
|
7922
|
+
)) })
|
|
7923
|
+
] }),
|
|
7924
|
+
data.type === "no-logistics" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground p-3 bg-muted/50 rounded-lg", children: [
|
|
7925
|
+
/* @__PURE__ */ jsx(Truck, { className: "h-4 w-4" }),
|
|
7926
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "No logistics scheduled for this week" })
|
|
7927
|
+
] }),
|
|
7928
|
+
data.hasWarning && data.warningMessage && /* @__PURE__ */ 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: [
|
|
7929
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }),
|
|
7930
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm", children: data.warningMessage })
|
|
7931
|
+
] }),
|
|
7932
|
+
data.notes && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
7933
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Notes" }),
|
|
7934
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: data.notes })
|
|
7935
|
+
] })
|
|
7936
|
+
] }) })
|
|
7937
|
+
] });
|
|
7938
|
+
}
|
|
7939
|
+
function WeekDetailDialog({
|
|
7940
|
+
open,
|
|
7941
|
+
onOpenChange,
|
|
7942
|
+
supplier,
|
|
7943
|
+
week,
|
|
7944
|
+
data,
|
|
7945
|
+
onProgressUpdate,
|
|
7946
|
+
onAddProductionComment,
|
|
7947
|
+
onAddDeliveryComment
|
|
7948
|
+
}) {
|
|
7949
|
+
const production = data?.production;
|
|
7950
|
+
const initialProduced = production?.produced ?? 0;
|
|
7951
|
+
const [producedValue, setProducedValue] = React22.useState(initialProduced.toString());
|
|
7952
|
+
const [hasChanges, setHasChanges] = React22.useState(false);
|
|
7953
|
+
const [selectedDelivery, setSelectedDelivery] = React22.useState(null);
|
|
7954
|
+
React22.useEffect(() => {
|
|
7955
|
+
const newProduced = data?.production?.produced ?? 0;
|
|
7956
|
+
setProducedValue(newProduced.toString());
|
|
7957
|
+
setHasChanges(false);
|
|
7958
|
+
}, [data]);
|
|
7959
|
+
React22.useEffect(() => {
|
|
7960
|
+
if (!open) {
|
|
7961
|
+
setSelectedDelivery(null);
|
|
7962
|
+
}
|
|
7963
|
+
}, [open]);
|
|
7964
|
+
const handleProducedChange = (e) => {
|
|
7965
|
+
const value = e.target.value;
|
|
7966
|
+
setProducedValue(value);
|
|
7967
|
+
setHasChanges(true);
|
|
7968
|
+
};
|
|
7969
|
+
const handleSave = () => {
|
|
7970
|
+
if (!supplier || !week || !onProgressUpdate) return;
|
|
7971
|
+
const newProduced = parseFloat(producedValue) || 0;
|
|
7972
|
+
const target = production?.target || 100;
|
|
7973
|
+
const newProgress = Math.min(100, Math.round(newProduced / target * 100));
|
|
7974
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
7975
|
+
onProgressUpdate(supplier.id, weekKey, newProgress, newProduced);
|
|
7976
|
+
setHasChanges(false);
|
|
7977
|
+
};
|
|
7978
|
+
if (!supplier || !week || !data) {
|
|
7979
|
+
return null;
|
|
7980
|
+
}
|
|
7981
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "max-w-lg max-h-[85vh] p-0 gap-0 overflow-hidden", children: selectedDelivery ? /* @__PURE__ */ jsx(
|
|
7982
|
+
DeliveryDetailsView,
|
|
7983
|
+
{
|
|
7984
|
+
delivery: selectedDelivery,
|
|
7985
|
+
week,
|
|
7986
|
+
onBack: () => setSelectedDelivery(null),
|
|
7987
|
+
onAddComment: onAddDeliveryComment ? (text) => {
|
|
7988
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
7989
|
+
onAddDeliveryComment(supplier.id, weekKey, selectedDelivery.id, text);
|
|
7990
|
+
} : void 0
|
|
7991
|
+
}
|
|
7992
|
+
) : /* @__PURE__ */ jsx(
|
|
7993
|
+
MainView,
|
|
7994
|
+
{
|
|
7995
|
+
supplier,
|
|
7996
|
+
week,
|
|
7997
|
+
data,
|
|
7998
|
+
producedValue,
|
|
7999
|
+
hasChanges,
|
|
8000
|
+
onProducedChange: handleProducedChange,
|
|
8001
|
+
onSave: handleSave,
|
|
8002
|
+
onSelectDelivery: setSelectedDelivery,
|
|
8003
|
+
onAddProductionComment: onAddProductionComment ? (text) => {
|
|
8004
|
+
const weekKey = `${week.year}-W${week.weekNumber.toString().padStart(2, "0")}`;
|
|
8005
|
+
onAddProductionComment(supplier.id, weekKey, text);
|
|
8006
|
+
} : void 0
|
|
8007
|
+
}
|
|
8008
|
+
) }) });
|
|
8009
|
+
}
|
|
8010
|
+
function RowHeaderCell({
|
|
8011
|
+
className,
|
|
8012
|
+
data,
|
|
8013
|
+
showProgress = true,
|
|
8014
|
+
...props
|
|
8015
|
+
}) {
|
|
8016
|
+
const progressPercent = data.totalRequired > 0 ? Math.min(data.totalBooked / data.totalRequired * 100, 100) : 0;
|
|
8017
|
+
return /* @__PURE__ */ jsxs(
|
|
8018
|
+
"div",
|
|
8019
|
+
{
|
|
8020
|
+
"data-slot": "row-header-cell",
|
|
8021
|
+
className: cn(
|
|
8022
|
+
"flex flex-col justify-center gap-1.5 py-2 px-3 min-w-[200px] h-[100px] bg-background",
|
|
8023
|
+
className
|
|
8024
|
+
),
|
|
8025
|
+
...props,
|
|
8026
|
+
children: [
|
|
8027
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
8028
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
8029
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-bold leading-tight text-foreground truncate", children: data.name }),
|
|
8030
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: data.typeCode })
|
|
8031
|
+
] }),
|
|
8032
|
+
/* @__PURE__ */ jsxs(
|
|
8033
|
+
Badge,
|
|
8034
|
+
{
|
|
8035
|
+
variant: "outline",
|
|
8036
|
+
className: "text-[10px] px-2 py-0.5 h-[19px] font-medium shrink-0 gap-1 bg-background border-border",
|
|
8037
|
+
children: [
|
|
8038
|
+
/* @__PURE__ */ jsx(Flag, { className: "h-2.5 w-2.5" }),
|
|
8039
|
+
"Paint"
|
|
8040
|
+
]
|
|
8041
|
+
}
|
|
8042
|
+
)
|
|
8043
|
+
] }),
|
|
8044
|
+
showProgress && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
8045
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
8046
|
+
"div",
|
|
8047
|
+
{
|
|
8048
|
+
className: "h-full bg-primary rounded-full transition-all",
|
|
8049
|
+
style: { width: `${progressPercent}%` }
|
|
8050
|
+
}
|
|
8051
|
+
) }),
|
|
8052
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] font-medium text-primary", children: [
|
|
8053
|
+
data.totalBooked.toLocaleString(),
|
|
8054
|
+
" / ",
|
|
8055
|
+
data.totalRequired.toLocaleString(),
|
|
8056
|
+
" Booked"
|
|
8057
|
+
] })
|
|
8058
|
+
] })
|
|
8059
|
+
]
|
|
8060
|
+
}
|
|
8061
|
+
);
|
|
8062
|
+
}
|
|
8063
|
+
function NetBadge({
|
|
8064
|
+
className,
|
|
8065
|
+
net,
|
|
8066
|
+
status,
|
|
8067
|
+
compact = false,
|
|
8068
|
+
...props
|
|
8069
|
+
}) {
|
|
8070
|
+
const statusStyles = {
|
|
8071
|
+
pending: {
|
|
8072
|
+
container: "bg-muted border-border/50",
|
|
8073
|
+
text: "text-muted-foreground",
|
|
8074
|
+
icon: "text-muted-foreground"
|
|
8075
|
+
},
|
|
8076
|
+
valid: {
|
|
8077
|
+
container: "bg-green-100/50 border-green-500 dark:bg-green-950/30 dark:border-green-400",
|
|
8078
|
+
text: "text-green-700 dark:text-green-400",
|
|
8079
|
+
icon: "text-green-600 dark:text-green-400"
|
|
8080
|
+
},
|
|
8081
|
+
shortfall: {
|
|
8082
|
+
container: "bg-red-100/30 border-red-400/50 dark:bg-red-950/30 dark:border-red-400/50",
|
|
8083
|
+
text: "text-red-700 dark:text-red-400",
|
|
8084
|
+
icon: "text-red-600 dark:text-red-400"
|
|
8085
|
+
}
|
|
8086
|
+
};
|
|
8087
|
+
const styles = statusStyles[status];
|
|
8088
|
+
return /* @__PURE__ */ jsxs(
|
|
8089
|
+
"div",
|
|
8090
|
+
{
|
|
8091
|
+
"data-slot": "net-badge",
|
|
8092
|
+
"data-status": status,
|
|
8093
|
+
className: cn(
|
|
8094
|
+
"inline-flex items-center gap-1.5 px-3 py-0.5 rounded-full border",
|
|
8095
|
+
styles.container,
|
|
8096
|
+
className
|
|
8097
|
+
),
|
|
8098
|
+
...props,
|
|
8099
|
+
children: [
|
|
8100
|
+
status === "valid" && /* @__PURE__ */ jsx(Check, { className: cn("h-3 w-3", styles.icon) }),
|
|
8101
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
8102
|
+
"text-xs font-bold leading-none",
|
|
8103
|
+
styles.text
|
|
8104
|
+
), children: net >= 0 ? net : net }),
|
|
8105
|
+
!compact && /* @__PURE__ */ jsx("span", { className: cn(
|
|
8106
|
+
"text-[10px] font-light opacity-80",
|
|
8107
|
+
styles.text
|
|
8108
|
+
), children: "net" })
|
|
8109
|
+
]
|
|
8110
|
+
}
|
|
8111
|
+
);
|
|
8112
|
+
}
|
|
8113
|
+
|
|
8114
|
+
// src/blocks/calibration-table/types.ts
|
|
8115
|
+
function formatCalibrationUnit(unit) {
|
|
8116
|
+
const unitLabels = {
|
|
8117
|
+
ton: "tons",
|
|
8118
|
+
pcs: "pcs",
|
|
8119
|
+
m2: "m\xB2",
|
|
8120
|
+
kg: "kg",
|
|
8121
|
+
m: "m"
|
|
8122
|
+
};
|
|
8123
|
+
return unitLabels[unit] || unit;
|
|
8124
|
+
}
|
|
8125
|
+
function calculateCalibrationCells(weeks) {
|
|
8126
|
+
const result = {};
|
|
8127
|
+
let accumulatedPlanned = 0;
|
|
8128
|
+
let accumulatedEntered = 0;
|
|
8129
|
+
for (const week of weeks) {
|
|
8130
|
+
accumulatedPlanned += week.planned;
|
|
8131
|
+
accumulatedEntered += week.entered ?? 0;
|
|
8132
|
+
const net = accumulatedEntered - accumulatedPlanned;
|
|
8133
|
+
let status = "pending";
|
|
8134
|
+
if (week.entered !== null) {
|
|
8135
|
+
status = net >= 0 ? "valid" : "shortfall";
|
|
8136
|
+
}
|
|
8137
|
+
result[week.weekKey] = {
|
|
8138
|
+
planned: week.planned,
|
|
8139
|
+
entered: week.entered,
|
|
8140
|
+
accumulatedPlanned,
|
|
8141
|
+
accumulatedEntered,
|
|
8142
|
+
net,
|
|
8143
|
+
status,
|
|
8144
|
+
isEditable: true
|
|
8145
|
+
};
|
|
8146
|
+
}
|
|
8147
|
+
return result;
|
|
8148
|
+
}
|
|
8149
|
+
function canSubmitCalibration(prefixes) {
|
|
8150
|
+
let shortfallCount = 0;
|
|
8151
|
+
let pendingCount = 0;
|
|
8152
|
+
for (const prefix of prefixes) {
|
|
8153
|
+
for (const weekKey in prefix.weeks) {
|
|
8154
|
+
const cell = prefix.weeks[weekKey];
|
|
8155
|
+
if (cell.status === "shortfall") shortfallCount++;
|
|
8156
|
+
if (cell.status === "pending") pendingCount++;
|
|
8157
|
+
}
|
|
8158
|
+
}
|
|
8159
|
+
const canSubmit = shortfallCount === 0 && pendingCount === 0;
|
|
8160
|
+
let message = "";
|
|
8161
|
+
if (shortfallCount > 0) {
|
|
8162
|
+
message = `Resolve ${shortfallCount} shortfall${shortfallCount > 1 ? "s" : ""} to submit`;
|
|
8163
|
+
} else if (pendingCount > 0) {
|
|
8164
|
+
message = `Enter production amounts for ${pendingCount} week${pendingCount > 1 ? "s" : ""}`;
|
|
8165
|
+
} else {
|
|
8166
|
+
message = "Ready to submit";
|
|
8167
|
+
}
|
|
8168
|
+
return { canSubmit, shortfallCount, pendingCount, message };
|
|
8169
|
+
}
|
|
8170
|
+
function CalibrationWeekCell({
|
|
8171
|
+
className,
|
|
8172
|
+
data,
|
|
8173
|
+
unit,
|
|
8174
|
+
onValueChange,
|
|
8175
|
+
isFocused,
|
|
8176
|
+
forcedRed = false,
|
|
8177
|
+
isEmpty = false,
|
|
8178
|
+
onAddClick,
|
|
8179
|
+
...props
|
|
8180
|
+
}) {
|
|
8181
|
+
const inputRef = React22.useRef(null);
|
|
8182
|
+
const [localValue, setLocalValue] = React22.useState(
|
|
8183
|
+
data.entered !== null ? String(data.entered) : ""
|
|
8184
|
+
);
|
|
8185
|
+
const [isHovered, setIsHovered] = React22.useState(false);
|
|
8186
|
+
const [isEditing, setIsEditing] = React22.useState(false);
|
|
8187
|
+
React22.useEffect(() => {
|
|
8188
|
+
setLocalValue(data.entered !== null ? String(data.entered) : "");
|
|
8189
|
+
}, [data.entered]);
|
|
8190
|
+
const unitLabel = formatCalibrationUnit(unit);
|
|
8191
|
+
const effectiveStatus = forcedRed ? "forcedRed" : data.status;
|
|
8192
|
+
const handleInputChange = (e) => {
|
|
8193
|
+
const val = e.target.value;
|
|
8194
|
+
setLocalValue(val);
|
|
8195
|
+
if (val === "" || val === "-") {
|
|
8196
|
+
onValueChange?.(null);
|
|
8197
|
+
} else {
|
|
8198
|
+
const numVal = parseFloat(val);
|
|
8199
|
+
if (!isNaN(numVal)) {
|
|
8200
|
+
onValueChange?.(numVal);
|
|
8201
|
+
}
|
|
8202
|
+
}
|
|
8203
|
+
};
|
|
8204
|
+
const handleBlur = () => {
|
|
8205
|
+
setIsEditing(false);
|
|
8206
|
+
if (localValue === "" || localValue === "-") {
|
|
8207
|
+
setLocalValue("");
|
|
8208
|
+
onValueChange?.(null);
|
|
8209
|
+
} else {
|
|
8210
|
+
const numVal = parseFloat(localValue);
|
|
8211
|
+
if (!isNaN(numVal)) {
|
|
8212
|
+
setLocalValue(String(numVal));
|
|
8213
|
+
onValueChange?.(numVal);
|
|
8214
|
+
}
|
|
8215
|
+
}
|
|
8216
|
+
};
|
|
8217
|
+
const handleAddClick = () => {
|
|
8218
|
+
setIsEditing(true);
|
|
8219
|
+
onAddClick?.();
|
|
8220
|
+
setTimeout(() => {
|
|
8221
|
+
inputRef.current?.focus();
|
|
8222
|
+
}, 0);
|
|
8223
|
+
};
|
|
8224
|
+
const getContainerStyles = () => {
|
|
8225
|
+
switch (effectiveStatus) {
|
|
8226
|
+
case "valid":
|
|
8227
|
+
return "border-l-2 border-l-green-500 bg-green-50/50 dark:bg-green-950/30";
|
|
8228
|
+
case "shortfall":
|
|
8229
|
+
case "forcedRed":
|
|
8230
|
+
return "border-l-2 border-l-red-500 bg-red-50/50 dark:bg-red-950/30";
|
|
8231
|
+
case "pending":
|
|
8232
|
+
default:
|
|
8233
|
+
return cn(
|
|
8234
|
+
"bg-background",
|
|
8235
|
+
isHovered ? "border-l-2 border-l-border" : "border-l-2 border-l-transparent"
|
|
8236
|
+
);
|
|
8237
|
+
}
|
|
8238
|
+
};
|
|
8239
|
+
const getInputStyles = () => {
|
|
8240
|
+
switch (effectiveStatus) {
|
|
8241
|
+
case "valid":
|
|
8242
|
+
return "text-green-700 dark:text-green-400";
|
|
8243
|
+
case "shortfall":
|
|
8244
|
+
case "forcedRed":
|
|
8245
|
+
return "text-red-700 dark:text-red-400 font-semibold";
|
|
8246
|
+
default:
|
|
8247
|
+
return "text-foreground";
|
|
8248
|
+
}
|
|
8249
|
+
};
|
|
8250
|
+
const showAddButton = isEmpty && effectiveStatus === "pending" && !isEditing && data.entered === null;
|
|
8251
|
+
if (showAddButton) {
|
|
8252
|
+
return /* @__PURE__ */ jsx(
|
|
8253
|
+
"div",
|
|
8254
|
+
{
|
|
8255
|
+
"data-slot": "calibration-week-cell",
|
|
8256
|
+
"data-status": "empty",
|
|
8257
|
+
className: cn(
|
|
8258
|
+
"flex items-center justify-center h-[100px]",
|
|
8259
|
+
"transition-all duration-200 ease-out",
|
|
8260
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8261
|
+
"bg-background",
|
|
8262
|
+
isHovered ? "border-l-2 border-l-border" : "border-l-2 border-l-transparent",
|
|
8263
|
+
className
|
|
8264
|
+
),
|
|
8265
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8266
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8267
|
+
...props,
|
|
8268
|
+
children: /* @__PURE__ */ jsxs(
|
|
8269
|
+
Button,
|
|
8270
|
+
{
|
|
8271
|
+
variant: "ghost",
|
|
8272
|
+
size: "icon",
|
|
8273
|
+
className: cn(
|
|
8274
|
+
"h-10 w-10 rounded-full",
|
|
8275
|
+
"text-muted-foreground/40 hover:text-muted-foreground hover:bg-muted/50",
|
|
8276
|
+
"transition-all duration-200",
|
|
8277
|
+
"shadow-[var(--j3m-shadow-sm)]"
|
|
8278
|
+
),
|
|
8279
|
+
onClick: handleAddClick,
|
|
8280
|
+
children: [
|
|
8281
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" }),
|
|
8282
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add production amount" })
|
|
8283
|
+
]
|
|
8284
|
+
}
|
|
8285
|
+
)
|
|
8286
|
+
}
|
|
8287
|
+
);
|
|
8288
|
+
}
|
|
8289
|
+
if (isEmpty && forcedRed) {
|
|
8290
|
+
return /* @__PURE__ */ jsxs(
|
|
8291
|
+
"div",
|
|
8292
|
+
{
|
|
8293
|
+
"data-slot": "calibration-week-cell",
|
|
8294
|
+
"data-status": "forcedRed",
|
|
8295
|
+
className: cn(
|
|
8296
|
+
"flex flex-col items-center justify-center gap-2 h-[100px] px-3 py-2",
|
|
8297
|
+
"transition-all duration-200 ease-out",
|
|
8298
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8299
|
+
"border-l-2 border-l-red-500 bg-red-50/50 dark:bg-red-950/30",
|
|
8300
|
+
className
|
|
8301
|
+
),
|
|
8302
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8303
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8304
|
+
...props,
|
|
8305
|
+
children: [
|
|
8306
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-red-600 dark:text-red-400 text-center", children: "Behind schedule" }),
|
|
8307
|
+
/* @__PURE__ */ jsx(NetBadge, { net: data.net, status: "shortfall" })
|
|
8308
|
+
]
|
|
8309
|
+
}
|
|
8310
|
+
);
|
|
8311
|
+
}
|
|
8312
|
+
return /* @__PURE__ */ jsxs(
|
|
8313
|
+
"div",
|
|
8314
|
+
{
|
|
8315
|
+
"data-slot": "calibration-week-cell",
|
|
8316
|
+
"data-status": effectiveStatus,
|
|
8317
|
+
className: cn(
|
|
8318
|
+
"flex flex-col gap-2 px-3 py-2 h-[100px]",
|
|
8319
|
+
// Hover lift effect with shadow (like planning table)
|
|
8320
|
+
"transition-all duration-200 ease-out",
|
|
8321
|
+
"hover:-translate-y-0.5 hover:shadow-[var(--j3m-shadow-md)]",
|
|
8322
|
+
getContainerStyles(),
|
|
8323
|
+
className
|
|
8324
|
+
),
|
|
8325
|
+
onMouseEnter: () => setIsHovered(true),
|
|
8326
|
+
onMouseLeave: () => setIsHovered(false),
|
|
8327
|
+
...props,
|
|
8328
|
+
children: [
|
|
8329
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8330
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-muted-foreground tracking-wide", children: "Accumulated" }),
|
|
8331
|
+
/* @__PURE__ */ jsx(NetBadge, { net: data.net, status: forcedRed ? "shortfall" : data.status })
|
|
8332
|
+
] }),
|
|
8333
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8334
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-muted-foreground tracking-wide", children: "Planned" }),
|
|
8335
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center px-2 py-0 bg-card border border-border rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-muted-foreground", children: data.planned }) })
|
|
8336
|
+
] }),
|
|
8337
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
8338
|
+
/* @__PURE__ */ jsx(
|
|
8339
|
+
Input,
|
|
8340
|
+
{
|
|
8341
|
+
ref: inputRef,
|
|
8342
|
+
type: "text",
|
|
8343
|
+
inputMode: "decimal",
|
|
8344
|
+
value: localValue,
|
|
8345
|
+
onChange: handleInputChange,
|
|
8346
|
+
onBlur: handleBlur,
|
|
8347
|
+
onFocus: () => setIsEditing(true),
|
|
8348
|
+
disabled: !data.isEditable,
|
|
8349
|
+
placeholder: "Enter amount",
|
|
8350
|
+
className: cn(
|
|
8351
|
+
"h-8 pl-3 pr-12 rounded-full text-sm font-semibold bg-background border-border",
|
|
8352
|
+
// Placeholder: smaller, lighter, lower contrast
|
|
8353
|
+
"placeholder:text-xs placeholder:font-normal placeholder:text-muted-foreground/50",
|
|
8354
|
+
getInputStyles(),
|
|
8355
|
+
!data.isEditable && "opacity-50 cursor-not-allowed"
|
|
8356
|
+
)
|
|
8357
|
+
}
|
|
8358
|
+
),
|
|
8359
|
+
/* @__PURE__ */ jsx("span", { className: "absolute right-4 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground/70 pointer-events-none", children: unitLabel })
|
|
8360
|
+
] })
|
|
8361
|
+
]
|
|
8362
|
+
}
|
|
8363
|
+
);
|
|
8364
|
+
}
|
|
8365
|
+
function CommentPopover({
|
|
8366
|
+
comments,
|
|
8367
|
+
weekLabel,
|
|
8368
|
+
availablePrefixes,
|
|
8369
|
+
onAddComment,
|
|
8370
|
+
open,
|
|
8371
|
+
onOpenChange
|
|
8372
|
+
}) {
|
|
8373
|
+
const [newCommentText, setNewCommentText] = React22.useState("");
|
|
8374
|
+
const [selectedPrefixId, setSelectedPrefixId] = React22.useState("");
|
|
8375
|
+
const [viewCommentsOpen, setViewCommentsOpen] = React22.useState(true);
|
|
8376
|
+
const [showAddForm, setShowAddForm] = React22.useState(false);
|
|
8377
|
+
const selectedPrefixName = React22.useMemo(() => {
|
|
8378
|
+
const prefix = availablePrefixes.find((p) => p.id === selectedPrefixId);
|
|
8379
|
+
return prefix?.name ?? "";
|
|
8380
|
+
}, [availablePrefixes, selectedPrefixId]);
|
|
8381
|
+
const handleSubmit = () => {
|
|
8382
|
+
if (newCommentText.trim() && selectedPrefixId) {
|
|
8383
|
+
onAddComment?.(newCommentText.trim(), selectedPrefixId, selectedPrefixName);
|
|
8384
|
+
setNewCommentText("");
|
|
8385
|
+
setSelectedPrefixId("");
|
|
8386
|
+
setShowAddForm(false);
|
|
8387
|
+
setViewCommentsOpen(true);
|
|
8388
|
+
}
|
|
8389
|
+
};
|
|
8390
|
+
const handleKeyDown = (e) => {
|
|
8391
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
8392
|
+
e.preventDefault();
|
|
8393
|
+
handleSubmit();
|
|
8394
|
+
}
|
|
8395
|
+
if (e.key === "Escape") {
|
|
8396
|
+
setShowAddForm(false);
|
|
8397
|
+
setSelectedPrefixId("");
|
|
8398
|
+
setNewCommentText("");
|
|
8399
|
+
}
|
|
8400
|
+
};
|
|
8401
|
+
const formatDate2 = (date) => {
|
|
8402
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
8403
|
+
month: "short",
|
|
8404
|
+
day: "numeric",
|
|
8405
|
+
hour: "numeric",
|
|
8406
|
+
minute: "2-digit"
|
|
8407
|
+
}).format(date);
|
|
8408
|
+
};
|
|
8409
|
+
const prevOpenRef = React22.useRef(open);
|
|
8410
|
+
React22.useEffect(() => {
|
|
8411
|
+
const wasOpen = prevOpenRef.current;
|
|
8412
|
+
prevOpenRef.current = open;
|
|
8413
|
+
if (wasOpen && !open) {
|
|
8414
|
+
setShowAddForm(false);
|
|
8415
|
+
setNewCommentText("");
|
|
8416
|
+
setSelectedPrefixId("");
|
|
8417
|
+
}
|
|
8418
|
+
}, [open]);
|
|
8419
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange, children: [
|
|
8420
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(CommentButton, { commentCount: comments.length }) }),
|
|
8421
|
+
/* @__PURE__ */ jsxs(
|
|
8422
|
+
PopoverContent,
|
|
8423
|
+
{
|
|
8424
|
+
className: "w-80 p-0 z-[100]",
|
|
8425
|
+
align: "end",
|
|
8426
|
+
sideOffset: 8,
|
|
8427
|
+
collisionPadding: 16,
|
|
8428
|
+
children: [
|
|
8429
|
+
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-border", children: [
|
|
8430
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children: "Comments" }),
|
|
8431
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: weekLabel })
|
|
8432
|
+
] }),
|
|
8433
|
+
/* @__PURE__ */ jsxs("div", { className: "p-2 space-y-2 max-h-[400px] overflow-y-auto", children: [
|
|
8434
|
+
/* @__PURE__ */ jsxs(Collapsible, { open: viewCommentsOpen, onOpenChange: setViewCommentsOpen, children: [
|
|
8435
|
+
/* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
8436
|
+
Button,
|
|
8437
|
+
{
|
|
8438
|
+
variant: "ghost",
|
|
8439
|
+
size: "sm",
|
|
8440
|
+
className: "w-full justify-between h-8 px-2",
|
|
8441
|
+
children: [
|
|
8442
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [
|
|
8443
|
+
"Comments ",
|
|
8444
|
+
comments.length > 0 && `(${comments.length})`
|
|
8445
|
+
] }),
|
|
8446
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: cn(
|
|
8447
|
+
"h-4 w-4 transition-transform duration-200",
|
|
8448
|
+
viewCommentsOpen && "rotate-180"
|
|
8449
|
+
) })
|
|
8450
|
+
]
|
|
8451
|
+
}
|
|
8452
|
+
) }),
|
|
8453
|
+
/* @__PURE__ */ jsx(CollapsibleContent2, { className: "space-y-2 pt-2", children: comments.length > 0 ? comments.map((comment) => /* @__PURE__ */ jsxs(
|
|
8454
|
+
"div",
|
|
8455
|
+
{
|
|
8456
|
+
className: "rounded-lg bg-muted/50 p-3 space-y-2",
|
|
8457
|
+
"aria-label": `Comment by ${comment.author} about ${comment.prefixName}`,
|
|
8458
|
+
children: [
|
|
8459
|
+
/* @__PURE__ */ jsx(
|
|
8460
|
+
Badge,
|
|
8461
|
+
{
|
|
8462
|
+
variant: "outline",
|
|
8463
|
+
className: "text-[10px] px-2 py-0 h-5 font-medium bg-background",
|
|
8464
|
+
children: comment.prefixName
|
|
8465
|
+
}
|
|
8466
|
+
),
|
|
8467
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8468
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: comment.author }),
|
|
8469
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatDate2(comment.createdAt) })
|
|
8470
|
+
] }),
|
|
8471
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: comment.text })
|
|
8472
|
+
]
|
|
8473
|
+
},
|
|
8474
|
+
comment.id
|
|
8475
|
+
)) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "No comments yet" }) })
|
|
8476
|
+
] }),
|
|
8477
|
+
/* @__PURE__ */ jsx(Separator, { className: "my-2" }),
|
|
8478
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: !showAddForm ? (
|
|
8479
|
+
/* Add comment Button */
|
|
8480
|
+
/* @__PURE__ */ jsxs(
|
|
8481
|
+
Button,
|
|
8482
|
+
{
|
|
8483
|
+
variant: "outline",
|
|
8484
|
+
size: "sm",
|
|
8485
|
+
className: "w-full justify-center gap-2 h-8",
|
|
8486
|
+
onClick: () => setShowAddForm(true),
|
|
8487
|
+
children: [
|
|
8488
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
|
|
8489
|
+
"Add comment"
|
|
8490
|
+
]
|
|
8491
|
+
}
|
|
8492
|
+
)
|
|
8493
|
+
) : (
|
|
8494
|
+
/* Comment input form with smooth expand animation */
|
|
8495
|
+
/* @__PURE__ */ jsxs(
|
|
8496
|
+
"div",
|
|
8497
|
+
{
|
|
8498
|
+
className: cn(
|
|
8499
|
+
"space-y-3 p-3 rounded-lg border border-border bg-muted/30",
|
|
8500
|
+
"animate-in fade-in-0 slide-in-from-top-2 duration-200"
|
|
8501
|
+
),
|
|
8502
|
+
children: [
|
|
8503
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
8504
|
+
/* @__PURE__ */ jsxs(Label2, { htmlFor: "prefix-select", className: "text-xs font-medium", children: [
|
|
8505
|
+
"Applies to ",
|
|
8506
|
+
/* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
|
|
8507
|
+
] }),
|
|
8508
|
+
/* @__PURE__ */ jsxs(Select, { value: selectedPrefixId, onValueChange: setSelectedPrefixId, children: [
|
|
8509
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: "prefix-select", size: "sm", className: "w-full", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select row/type..." }) }),
|
|
8510
|
+
/* @__PURE__ */ jsx(SelectContent, { children: availablePrefixes.map((prefix) => /* @__PURE__ */ jsx(SelectItem, { value: prefix.id, children: prefix.name }, prefix.id)) })
|
|
8511
|
+
] })
|
|
8512
|
+
] }),
|
|
8513
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
8514
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "comment-text", className: "text-xs font-medium", children: "Comment" }),
|
|
8515
|
+
/* @__PURE__ */ jsx(
|
|
8516
|
+
Textarea,
|
|
8517
|
+
{
|
|
8518
|
+
id: "comment-text",
|
|
8519
|
+
placeholder: "Type your comment...",
|
|
8520
|
+
value: newCommentText,
|
|
8521
|
+
onChange: (e) => setNewCommentText(e.target.value),
|
|
8522
|
+
onKeyDown: handleKeyDown,
|
|
8523
|
+
className: "min-h-[80px] text-sm resize-none",
|
|
8524
|
+
autoFocus: true
|
|
8525
|
+
}
|
|
8526
|
+
)
|
|
8527
|
+
] }),
|
|
8528
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8529
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "\u2318+Enter to send \xB7 Esc to cancel" }),
|
|
8530
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8531
|
+
/* @__PURE__ */ jsx(
|
|
8532
|
+
Button,
|
|
8533
|
+
{
|
|
8534
|
+
variant: "ghost",
|
|
8535
|
+
size: "sm",
|
|
8536
|
+
className: "h-7",
|
|
8537
|
+
onClick: () => {
|
|
8538
|
+
setShowAddForm(false);
|
|
8539
|
+
setNewCommentText("");
|
|
8540
|
+
setSelectedPrefixId("");
|
|
8541
|
+
},
|
|
8542
|
+
children: "Cancel"
|
|
8543
|
+
}
|
|
8544
|
+
),
|
|
8545
|
+
/* @__PURE__ */ jsxs(
|
|
8546
|
+
Button,
|
|
8547
|
+
{
|
|
8548
|
+
size: "sm",
|
|
8549
|
+
className: "h-7 gap-1",
|
|
8550
|
+
onClick: handleSubmit,
|
|
8551
|
+
disabled: !newCommentText.trim() || !selectedPrefixId,
|
|
8552
|
+
children: [
|
|
8553
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3 w-3" }),
|
|
8554
|
+
"Save"
|
|
8555
|
+
]
|
|
8556
|
+
}
|
|
8557
|
+
)
|
|
8558
|
+
] })
|
|
8559
|
+
] })
|
|
8560
|
+
]
|
|
8561
|
+
}
|
|
8562
|
+
)
|
|
8563
|
+
) })
|
|
8564
|
+
] })
|
|
8565
|
+
]
|
|
8566
|
+
}
|
|
8567
|
+
)
|
|
8568
|
+
] });
|
|
8569
|
+
}
|
|
8570
|
+
function CalibrationWeekHeader({
|
|
8571
|
+
className,
|
|
8572
|
+
week,
|
|
8573
|
+
comments = [],
|
|
8574
|
+
showCommentButton = true,
|
|
8575
|
+
availablePrefixes = [],
|
|
8576
|
+
onAddComment,
|
|
8577
|
+
...props
|
|
8578
|
+
}) {
|
|
8579
|
+
return /* @__PURE__ */ jsxs(
|
|
8580
|
+
"div",
|
|
8581
|
+
{
|
|
8582
|
+
"data-slot": "calibration-week-header",
|
|
8583
|
+
"data-current-week": week.isCurrentWeek,
|
|
8584
|
+
className: cn(
|
|
8585
|
+
"flex items-center justify-between gap-2 px-2 py-2 min-w-[200px]",
|
|
8586
|
+
className
|
|
8587
|
+
),
|
|
8588
|
+
...props,
|
|
8589
|
+
children: [
|
|
8590
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
8591
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8592
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
8593
|
+
"text-sm font-semibold tracking-tight",
|
|
8594
|
+
week.isCurrentWeek ? "text-primary" : "text-foreground"
|
|
8595
|
+
), children: week.label }),
|
|
8596
|
+
week.isCurrentWeek && /* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
8597
|
+
/* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75" }),
|
|
8598
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary" })
|
|
8599
|
+
] })
|
|
8600
|
+
] }),
|
|
8601
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-normal text-muted-foreground/60", children: week.dateRange })
|
|
8602
|
+
] }),
|
|
8603
|
+
showCommentButton && availablePrefixes.length > 0 && /* @__PURE__ */ jsx(
|
|
8604
|
+
CommentPopover,
|
|
8605
|
+
{
|
|
8606
|
+
comments,
|
|
8607
|
+
weekLabel: week.label,
|
|
8608
|
+
availablePrefixes,
|
|
8609
|
+
onAddComment
|
|
8610
|
+
}
|
|
8611
|
+
)
|
|
8612
|
+
]
|
|
8613
|
+
}
|
|
8614
|
+
);
|
|
8615
|
+
}
|
|
8616
|
+
function CalibrationTable({
|
|
8617
|
+
className,
|
|
8618
|
+
prefixes,
|
|
8619
|
+
supplierName,
|
|
8620
|
+
status = "draft",
|
|
8621
|
+
config = {}
|
|
8622
|
+
}) {
|
|
8623
|
+
const {
|
|
8624
|
+
weekCount = 8,
|
|
8625
|
+
startDate,
|
|
8626
|
+
allowTimelineExtension = true,
|
|
8627
|
+
maxEarlierWeeks = 4,
|
|
8628
|
+
showToolbar = true,
|
|
8629
|
+
showPagination = true,
|
|
8630
|
+
pageSizeOptions = [10, 20, 30],
|
|
8631
|
+
defaultPageSize = 10,
|
|
8632
|
+
stickyRowHeader = true,
|
|
8633
|
+
maxHeight = "500px",
|
|
8634
|
+
onCellChange,
|
|
8635
|
+
onSubmit,
|
|
8636
|
+
onAddComment,
|
|
8637
|
+
onAddEarlierWeek
|
|
8638
|
+
} = config;
|
|
8639
|
+
const calculatedStartDate = React22.useMemo(() => {
|
|
8640
|
+
if (startDate) return startDate;
|
|
8641
|
+
let earliest = null;
|
|
8642
|
+
for (const prefix of prefixes) {
|
|
8643
|
+
for (const weekKey in prefix.weeks) {
|
|
8644
|
+
const cell = prefix.weeks[weekKey];
|
|
8645
|
+
if (cell.planned > 0) {
|
|
8646
|
+
const match = weekKey.match(/(\d{4})-W(\d{2})/);
|
|
8647
|
+
if (match) {
|
|
8648
|
+
const year = parseInt(match[1]);
|
|
8649
|
+
const week = parseInt(match[2]);
|
|
8650
|
+
const date = new Date(year, 0, 1 + (week - 1) * 7);
|
|
8651
|
+
if (earliest === null || date < earliest) {
|
|
8652
|
+
earliest = date;
|
|
8653
|
+
}
|
|
8654
|
+
}
|
|
8655
|
+
}
|
|
8656
|
+
}
|
|
8657
|
+
}
|
|
8658
|
+
return earliest ?? /* @__PURE__ */ new Date();
|
|
8659
|
+
}, [startDate, prefixes]);
|
|
8660
|
+
const [additionalWeeks, setAdditionalWeeks] = React22.useState(0);
|
|
8661
|
+
const weeks = React22.useMemo(() => {
|
|
8662
|
+
const start = new Date(calculatedStartDate);
|
|
8663
|
+
start.setDate(start.getDate() - additionalWeeks * 7);
|
|
8664
|
+
return generateWeeks(start, weekCount + additionalWeeks);
|
|
8665
|
+
}, [calculatedStartDate, weekCount, additionalWeeks]);
|
|
8666
|
+
React22.useMemo(() => {
|
|
8667
|
+
const currentWeek = weeks.find((w) => w.isCurrentWeek);
|
|
8668
|
+
return currentWeek ? getWeekKey(currentWeek.startDate) : null;
|
|
8669
|
+
}, [weeks]);
|
|
8670
|
+
const [currentPage, setCurrentPage] = React22.useState(0);
|
|
8671
|
+
const [pageSize, setPageSize] = React22.useState(defaultPageSize);
|
|
8672
|
+
const [searchQuery, setSearchQuery] = React22.useState("");
|
|
8673
|
+
const filteredPrefixes = React22.useMemo(() => {
|
|
8674
|
+
if (!searchQuery) return prefixes;
|
|
8675
|
+
const query = searchQuery.toLowerCase();
|
|
8676
|
+
return prefixes.filter(
|
|
8677
|
+
(p) => p.name.toLowerCase().includes(query) || p.typeCode.toLowerCase().includes(query)
|
|
8678
|
+
);
|
|
8679
|
+
}, [prefixes, searchQuery]);
|
|
8680
|
+
const paginatedPrefixes = React22.useMemo(() => {
|
|
8681
|
+
const start = currentPage * pageSize;
|
|
8682
|
+
return filteredPrefixes.slice(start, start + pageSize);
|
|
8683
|
+
}, [filteredPrefixes, currentPage, pageSize]);
|
|
8684
|
+
React22.useMemo(
|
|
8685
|
+
() => canSubmitCalibration(prefixes),
|
|
8686
|
+
[prefixes]
|
|
8687
|
+
);
|
|
8688
|
+
const handleAddEarlierWeek = () => {
|
|
8689
|
+
if (additionalWeeks < maxEarlierWeeks) {
|
|
8690
|
+
setAdditionalWeeks((prev) => prev + 1);
|
|
8691
|
+
onAddEarlierWeek?.();
|
|
8692
|
+
}
|
|
8693
|
+
};
|
|
8694
|
+
const handleCellChange = (prefixId, weekKey, value) => {
|
|
8695
|
+
onCellChange?.(prefixId, weekKey, value);
|
|
8696
|
+
};
|
|
8697
|
+
const handleAddWeekComment = (weekKey, text, prefixId, prefixName) => {
|
|
8698
|
+
onAddComment?.(prefixId, weekKey, text);
|
|
8699
|
+
};
|
|
8700
|
+
const getWeekComments = (weekKey) => {
|
|
8701
|
+
const allComments = [];
|
|
8702
|
+
for (const prefix of prefixes) {
|
|
8703
|
+
const weekComments = prefix.comments?.filter((c) => c.weekKey === weekKey) ?? [];
|
|
8704
|
+
allComments.push(...weekComments);
|
|
8705
|
+
}
|
|
8706
|
+
return allComments;
|
|
8707
|
+
};
|
|
8708
|
+
const availablePrefixes = React22.useMemo(
|
|
8709
|
+
() => prefixes.map((p) => ({ id: p.id, name: p.name })),
|
|
8710
|
+
[prefixes]
|
|
8711
|
+
);
|
|
8712
|
+
return /* @__PURE__ */ jsxs(
|
|
8713
|
+
"div",
|
|
8714
|
+
{
|
|
8715
|
+
"data-slot": "calibration-table",
|
|
8716
|
+
className: cn("flex flex-col gap-4", className),
|
|
8717
|
+
children: [
|
|
8718
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
8719
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: "Weekly Production Calibration" }),
|
|
8720
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Review required weekly production and confirm achievable output at the selected checkpoint." })
|
|
8721
|
+
] }) }),
|
|
8722
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8723
|
+
showToolbar && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
8724
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
8725
|
+
Input,
|
|
8726
|
+
{
|
|
8727
|
+
placeholder: "Search prefixes...",
|
|
8728
|
+
value: searchQuery,
|
|
8729
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
8730
|
+
className: "h-8 w-[200px] lg:w-[300px]"
|
|
8731
|
+
}
|
|
8732
|
+
) }),
|
|
8733
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: allowTimelineExtension && additionalWeeks < maxEarlierWeeks && /* @__PURE__ */ jsxs(
|
|
8734
|
+
Button,
|
|
8735
|
+
{
|
|
8736
|
+
variant: "outline",
|
|
8737
|
+
size: "sm",
|
|
8738
|
+
className: "gap-2",
|
|
8739
|
+
onClick: handleAddEarlierWeek,
|
|
8740
|
+
children: [
|
|
8741
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
8742
|
+
"Add earlier week"
|
|
8743
|
+
]
|
|
8744
|
+
}
|
|
8745
|
+
) })
|
|
8746
|
+
] }),
|
|
8747
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-xl border bg-background shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxs(
|
|
8748
|
+
ScrollArea,
|
|
8749
|
+
{
|
|
8750
|
+
className: "w-full",
|
|
8751
|
+
style: { maxHeight },
|
|
8752
|
+
children: [
|
|
8753
|
+
/* @__PURE__ */ jsxs("table", { className: "w-full border-collapse", children: [
|
|
8754
|
+
/* @__PURE__ */ jsx("thead", { className: "sticky top-0 z-20", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
8755
|
+
/* @__PURE__ */ jsx("th", { className: cn(
|
|
8756
|
+
"h-14 px-3 text-left align-middle font-semibold text-xs text-muted-foreground uppercase tracking-wide",
|
|
8757
|
+
"border-r border-b border-border bg-sidebar",
|
|
8758
|
+
stickyRowHeader && "sticky left-0 z-30 min-w-[200px]",
|
|
8759
|
+
// Right shadow using Quantum token
|
|
8760
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
8761
|
+
), children: "Supplier / Scope" }),
|
|
8762
|
+
weeks.map((week) => {
|
|
8763
|
+
const weekKey = getWeekKey(week.startDate);
|
|
8764
|
+
const weekComments = getWeekComments(weekKey);
|
|
8765
|
+
return /* @__PURE__ */ jsx(
|
|
8766
|
+
"th",
|
|
8767
|
+
{
|
|
8768
|
+
className: "h-14 px-2 text-left align-middle border-r border-b border-border last:border-r-0 min-w-[220px] bg-sidebar",
|
|
8769
|
+
children: /* @__PURE__ */ jsx(
|
|
8770
|
+
CalibrationWeekHeader,
|
|
8771
|
+
{
|
|
8772
|
+
week,
|
|
8773
|
+
comments: weekComments,
|
|
8774
|
+
showCommentButton: true,
|
|
8775
|
+
availablePrefixes,
|
|
8776
|
+
onAddComment: (text, prefixId, prefixName) => handleAddWeekComment(weekKey, text, prefixId)
|
|
8777
|
+
}
|
|
8778
|
+
)
|
|
8779
|
+
},
|
|
8780
|
+
weekKey
|
|
8781
|
+
);
|
|
8782
|
+
})
|
|
8783
|
+
] }) }),
|
|
8784
|
+
/* @__PURE__ */ jsx("tbody", { className: "bg-background", children: paginatedPrefixes.length > 0 ? paginatedPrefixes.map((prefix) => {
|
|
8785
|
+
const sortedWeekKeys = weeks.map((w) => getWeekKey(w.startDate));
|
|
8786
|
+
let hasDeficit = false;
|
|
8787
|
+
const forcedRedMap = {};
|
|
8788
|
+
for (const weekKey of sortedWeekKeys) {
|
|
8789
|
+
const cellData = prefix.weeks[weekKey];
|
|
8790
|
+
if (hasDeficit) {
|
|
8791
|
+
forcedRedMap[weekKey] = true;
|
|
8792
|
+
} else if (cellData && cellData.status === "shortfall") {
|
|
8793
|
+
hasDeficit = true;
|
|
8794
|
+
forcedRedMap[weekKey] = false;
|
|
8795
|
+
} else {
|
|
8796
|
+
forcedRedMap[weekKey] = false;
|
|
8797
|
+
}
|
|
8798
|
+
}
|
|
8799
|
+
return /* @__PURE__ */ jsxs("tr", { className: "border-b border-border last:border-b-0", children: [
|
|
8800
|
+
/* @__PURE__ */ jsx(
|
|
8801
|
+
"td",
|
|
8802
|
+
{
|
|
8803
|
+
className: cn(
|
|
8804
|
+
"p-0 align-top border-r border-border bg-background",
|
|
8805
|
+
stickyRowHeader && "sticky left-0 z-10 min-w-[200px]",
|
|
8806
|
+
// Right shadow using Quantum token
|
|
8807
|
+
stickyRowHeader && "shadow-[var(--j3m-shadow-sticky-edge)]"
|
|
8808
|
+
),
|
|
8809
|
+
children: /* @__PURE__ */ jsx(RowHeaderCell, { data: prefix, showProgress: true })
|
|
8810
|
+
}
|
|
8811
|
+
),
|
|
8812
|
+
weeks.map((week) => {
|
|
8813
|
+
const weekKey = getWeekKey(week.startDate);
|
|
8814
|
+
const cellData = prefix.weeks[weekKey];
|
|
8815
|
+
const isForcedRed = forcedRedMap[weekKey] ?? false;
|
|
8816
|
+
const isEmpty = !cellData || cellData.planned === 0;
|
|
8817
|
+
const effectiveCellData = cellData ?? {
|
|
8818
|
+
planned: 0,
|
|
8819
|
+
entered: null,
|
|
8820
|
+
accumulatedPlanned: 0,
|
|
8821
|
+
accumulatedEntered: 0,
|
|
8822
|
+
net: 0,
|
|
8823
|
+
status: "pending",
|
|
8824
|
+
isEditable: true
|
|
8825
|
+
};
|
|
8826
|
+
return /* @__PURE__ */ jsx(
|
|
8827
|
+
"td",
|
|
8828
|
+
{
|
|
8829
|
+
className: "p-0 align-top border-r border-border last:border-r-0 min-w-[220px] bg-background",
|
|
8830
|
+
children: /* @__PURE__ */ jsx(
|
|
8831
|
+
CalibrationWeekCell,
|
|
8832
|
+
{
|
|
8833
|
+
data: effectiveCellData,
|
|
8834
|
+
unit: prefix.unit,
|
|
8835
|
+
onValueChange: (value) => handleCellChange(prefix.id, weekKey, value),
|
|
8836
|
+
forcedRed: isForcedRed,
|
|
8837
|
+
isEmpty,
|
|
8838
|
+
onAddClick: () => {
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
8841
|
+
)
|
|
8842
|
+
},
|
|
8843
|
+
weekKey
|
|
8844
|
+
);
|
|
8845
|
+
})
|
|
8846
|
+
] }, prefix.id);
|
|
8847
|
+
}) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
8848
|
+
"td",
|
|
8849
|
+
{
|
|
8850
|
+
colSpan: weeks.length + 1,
|
|
8851
|
+
className: "h-24 text-center text-muted-foreground bg-background",
|
|
8852
|
+
children: "No prefixes found."
|
|
8853
|
+
}
|
|
8854
|
+
) }) })
|
|
8855
|
+
] }),
|
|
8856
|
+
/* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" }),
|
|
8857
|
+
/* @__PURE__ */ jsx(ScrollBar, { orientation: "vertical" })
|
|
8858
|
+
]
|
|
8859
|
+
}
|
|
8860
|
+
) })
|
|
8861
|
+
] }),
|
|
8862
|
+
showPagination && filteredPrefixes.length > pageSize && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-2", children: [
|
|
8863
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
8864
|
+
/* @__PURE__ */ jsx("span", { children: "Rows per page" }),
|
|
8865
|
+
/* @__PURE__ */ jsx(
|
|
8866
|
+
"select",
|
|
8867
|
+
{
|
|
8868
|
+
value: pageSize,
|
|
8869
|
+
onChange: (e) => {
|
|
8870
|
+
setPageSize(Number(e.target.value));
|
|
8871
|
+
setCurrentPage(0);
|
|
8872
|
+
},
|
|
8873
|
+
className: "h-8 w-16 rounded-md border bg-background px-2 text-sm",
|
|
8874
|
+
children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
8875
|
+
}
|
|
8876
|
+
)
|
|
8877
|
+
] }),
|
|
8878
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
8879
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
8880
|
+
"Page ",
|
|
8881
|
+
currentPage + 1,
|
|
8882
|
+
" of ",
|
|
8883
|
+
Math.ceil(filteredPrefixes.length / pageSize)
|
|
8884
|
+
] }),
|
|
8885
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8886
|
+
/* @__PURE__ */ jsx(
|
|
8887
|
+
Button,
|
|
8888
|
+
{
|
|
8889
|
+
variant: "outline",
|
|
8890
|
+
size: "icon",
|
|
8891
|
+
className: "h-8 w-8",
|
|
8892
|
+
disabled: currentPage === 0,
|
|
8893
|
+
onClick: () => setCurrentPage(0),
|
|
8894
|
+
children: "\xAB\xAB"
|
|
8895
|
+
}
|
|
8896
|
+
),
|
|
8897
|
+
/* @__PURE__ */ jsx(
|
|
8898
|
+
Button,
|
|
8899
|
+
{
|
|
8900
|
+
variant: "outline",
|
|
8901
|
+
size: "icon",
|
|
8902
|
+
className: "h-8 w-8",
|
|
8903
|
+
disabled: currentPage === 0,
|
|
8904
|
+
onClick: () => setCurrentPage((prev) => prev - 1),
|
|
8905
|
+
children: "\xAB"
|
|
8906
|
+
}
|
|
8907
|
+
),
|
|
8908
|
+
/* @__PURE__ */ jsx(
|
|
8909
|
+
Button,
|
|
8910
|
+
{
|
|
8911
|
+
variant: "outline",
|
|
8912
|
+
size: "icon",
|
|
8913
|
+
className: "h-8 w-8",
|
|
8914
|
+
disabled: currentPage >= Math.ceil(filteredPrefixes.length / pageSize) - 1,
|
|
8915
|
+
onClick: () => setCurrentPage((prev) => prev + 1),
|
|
8916
|
+
children: "\xBB"
|
|
8917
|
+
}
|
|
8918
|
+
),
|
|
8919
|
+
/* @__PURE__ */ jsx(
|
|
8920
|
+
Button,
|
|
8921
|
+
{
|
|
8922
|
+
variant: "outline",
|
|
8923
|
+
size: "icon",
|
|
8924
|
+
className: "h-8 w-8",
|
|
8925
|
+
disabled: currentPage >= Math.ceil(filteredPrefixes.length / pageSize) - 1,
|
|
8926
|
+
onClick: () => setCurrentPage(Math.ceil(filteredPrefixes.length / pageSize) - 1),
|
|
8927
|
+
children: "\xBB\xBB"
|
|
8928
|
+
}
|
|
8929
|
+
)
|
|
8930
|
+
] })
|
|
8931
|
+
] })
|
|
8932
|
+
] })
|
|
8933
|
+
]
|
|
8934
|
+
}
|
|
8935
|
+
);
|
|
8936
|
+
}
|
|
8937
|
+
function CommentDialog({
|
|
8938
|
+
prefixes,
|
|
8939
|
+
weeks,
|
|
8940
|
+
onAddComment,
|
|
8941
|
+
triggerVariant = "outline",
|
|
8942
|
+
open,
|
|
8943
|
+
onOpenChange
|
|
8944
|
+
}) {
|
|
8945
|
+
const [selectedPrefixId, setSelectedPrefixId] = React22.useState("");
|
|
8946
|
+
const [selectedWeekKey, setSelectedWeekKey] = React22.useState("");
|
|
8947
|
+
const [commentText, setCommentText] = React22.useState("");
|
|
8948
|
+
const currentWeek = React22.useMemo(
|
|
8949
|
+
() => weeks.find((w) => w.isCurrentWeek),
|
|
8950
|
+
[weeks]
|
|
8951
|
+
);
|
|
8952
|
+
React22.useEffect(() => {
|
|
8953
|
+
if (open) {
|
|
8954
|
+
setSelectedPrefixId(prefixes[0]?.id ?? "");
|
|
8955
|
+
setSelectedWeekKey(currentWeek ? getWeekKey(currentWeek.startDate) : weeks[0] ? getWeekKey(weeks[0].startDate) : "");
|
|
8956
|
+
setCommentText("");
|
|
8957
|
+
}
|
|
8958
|
+
}, [open, prefixes, weeks, currentWeek]);
|
|
8959
|
+
const handleSave = () => {
|
|
8960
|
+
if (selectedPrefixId && selectedWeekKey && commentText.trim()) {
|
|
8961
|
+
onAddComment?.(selectedPrefixId, selectedWeekKey, commentText.trim());
|
|
8962
|
+
onOpenChange?.(false);
|
|
8963
|
+
}
|
|
8964
|
+
};
|
|
8965
|
+
const isValid = selectedPrefixId && selectedWeekKey && commentText.trim();
|
|
8966
|
+
return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange, children: [
|
|
8967
|
+
/* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: triggerVariant, size: "sm", className: "gap-2", children: [
|
|
8968
|
+
/* @__PURE__ */ jsx(MessageSquarePlus, { className: "h-4 w-4" }),
|
|
8969
|
+
"Add comment"
|
|
8970
|
+
] }) }),
|
|
8971
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[425px]", children: [
|
|
8972
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
8973
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Add Comment" }),
|
|
8974
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "Add a comment to a specific prefix and week. Comments help communicate production updates and issues." })
|
|
8975
|
+
] }),
|
|
8976
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 py-4", children: [
|
|
8977
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8978
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "prefix-select", children: "Prefix / Element Type" }),
|
|
8979
|
+
/* @__PURE__ */ jsxs(Select, { value: selectedPrefixId, onValueChange: setSelectedPrefixId, children: [
|
|
8980
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: "prefix-select", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select prefix..." }) }),
|
|
8981
|
+
/* @__PURE__ */ jsx(SelectContent, { children: prefixes.map((prefix) => /* @__PURE__ */ jsx(SelectItem, { value: prefix.id, children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
8982
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: prefix.name }),
|
|
8983
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-xs", children: [
|
|
8984
|
+
"(",
|
|
8985
|
+
prefix.typeCode,
|
|
8986
|
+
")"
|
|
8987
|
+
] })
|
|
8988
|
+
] }) }, prefix.id)) })
|
|
8989
|
+
] })
|
|
8990
|
+
] }),
|
|
8991
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8992
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "week-select", children: "Week" }),
|
|
8993
|
+
/* @__PURE__ */ jsxs(Select, { value: selectedWeekKey, onValueChange: setSelectedWeekKey, children: [
|
|
8994
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: "week-select", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select week..." }) }),
|
|
8995
|
+
/* @__PURE__ */ jsx(SelectContent, { children: weeks.map((week) => {
|
|
8996
|
+
const weekKey = getWeekKey(week.startDate);
|
|
8997
|
+
return /* @__PURE__ */ jsx(SelectItem, { value: weekKey, children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
8998
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
8999
|
+
"font-medium",
|
|
9000
|
+
week.isCurrentWeek && "text-primary"
|
|
9001
|
+
), children: week.label }),
|
|
9002
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: week.dateRange }),
|
|
9003
|
+
week.isCurrentWeek && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-primary font-medium", children: "(Current)" })
|
|
9004
|
+
] }) }, weekKey);
|
|
9005
|
+
}) })
|
|
9006
|
+
] })
|
|
9007
|
+
] }),
|
|
9008
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
9009
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "comment-text", children: "Comment" }),
|
|
9010
|
+
/* @__PURE__ */ jsx(
|
|
9011
|
+
Textarea,
|
|
9012
|
+
{
|
|
9013
|
+
id: "comment-text",
|
|
9014
|
+
placeholder: "Enter your comment...",
|
|
9015
|
+
value: commentText,
|
|
9016
|
+
onChange: (e) => setCommentText(e.target.value),
|
|
9017
|
+
className: "min-h-[100px] resize-none"
|
|
9018
|
+
}
|
|
9019
|
+
)
|
|
9020
|
+
] })
|
|
9021
|
+
] }),
|
|
9022
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
9023
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => onOpenChange?.(false), children: "Cancel" }),
|
|
9024
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: !isValid, children: "Save comment" })
|
|
9025
|
+
] })
|
|
9026
|
+
] })
|
|
9027
|
+
] });
|
|
9028
|
+
}
|
|
9029
|
+
function getStatusBadge(status) {
|
|
9030
|
+
switch (status) {
|
|
9031
|
+
case "draft":
|
|
9032
|
+
return { variant: "secondary", label: "DRAFT", color: "bg-blue-500" };
|
|
9033
|
+
case "submitted":
|
|
9034
|
+
return { variant: "secondary", label: "SUBMITTED", color: "bg-amber-500" };
|
|
9035
|
+
case "approved":
|
|
9036
|
+
return { variant: "secondary", label: "APPROVED", color: "bg-green-500" };
|
|
9037
|
+
case "rejected":
|
|
9038
|
+
return { variant: "destructive", label: "REJECTED", color: "bg-red-500" };
|
|
9039
|
+
}
|
|
9040
|
+
}
|
|
9041
|
+
function formatDate(date) {
|
|
9042
|
+
return date.toLocaleDateString("en-US", {
|
|
9043
|
+
month: "short",
|
|
9044
|
+
day: "2-digit",
|
|
9045
|
+
year: "numeric"
|
|
9046
|
+
});
|
|
9047
|
+
}
|
|
9048
|
+
function SubmitCalibrationBar({
|
|
9049
|
+
className,
|
|
9050
|
+
status,
|
|
9051
|
+
lastSaved,
|
|
9052
|
+
canSubmit,
|
|
9053
|
+
shortfallCount,
|
|
9054
|
+
pendingCount,
|
|
9055
|
+
message,
|
|
9056
|
+
onSubmit,
|
|
9057
|
+
onSaveDraft,
|
|
9058
|
+
...props
|
|
9059
|
+
}) {
|
|
9060
|
+
const statusBadge = getStatusBadge(status);
|
|
9061
|
+
return /* @__PURE__ */ jsxs(
|
|
9062
|
+
"div",
|
|
9063
|
+
{
|
|
9064
|
+
"data-slot": "submit-calibration-bar",
|
|
9065
|
+
className: cn(
|
|
9066
|
+
"flex items-center justify-between gap-4 px-4 py-4",
|
|
9067
|
+
"bg-background",
|
|
9068
|
+
className
|
|
9069
|
+
),
|
|
9070
|
+
...props,
|
|
9071
|
+
children: [
|
|
9072
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9073
|
+
!canSubmit && (shortfallCount > 0 || pendingCount > 0) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
9074
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 text-amber-500" }),
|
|
9075
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: message })
|
|
9076
|
+
] }),
|
|
9077
|
+
canSubmit && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
9078
|
+
/* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4 text-green-500" }),
|
|
9079
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: message })
|
|
9080
|
+
] })
|
|
9081
|
+
] }),
|
|
9082
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9083
|
+
/* @__PURE__ */ jsxs(
|
|
9084
|
+
Badge,
|
|
9085
|
+
{
|
|
9086
|
+
variant: statusBadge.variant,
|
|
9087
|
+
className: "flex items-center gap-2 px-3 py-1 rounded-full",
|
|
9088
|
+
children: [
|
|
9089
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-2 w-2 rounded-full", statusBadge.color) }),
|
|
9090
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: statusBadge.label })
|
|
9091
|
+
]
|
|
9092
|
+
}
|
|
9093
|
+
),
|
|
9094
|
+
lastSaved && /* @__PURE__ */ jsxs(
|
|
9095
|
+
Button,
|
|
9096
|
+
{
|
|
9097
|
+
variant: "outline",
|
|
9098
|
+
size: "sm",
|
|
9099
|
+
className: "gap-2 rounded-full",
|
|
9100
|
+
disabled: true,
|
|
9101
|
+
children: [
|
|
9102
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "h-4 w-4" }),
|
|
9103
|
+
/* @__PURE__ */ jsx("span", { children: formatDate(lastSaved) })
|
|
9104
|
+
]
|
|
9105
|
+
}
|
|
9106
|
+
),
|
|
9107
|
+
/* @__PURE__ */ jsx(
|
|
9108
|
+
Button,
|
|
9109
|
+
{
|
|
9110
|
+
size: "sm",
|
|
9111
|
+
className: "rounded-full px-4 min-w-[140px]",
|
|
9112
|
+
disabled: !canSubmit || status === "submitted" || status === "approved",
|
|
9113
|
+
onClick: onSubmit,
|
|
9114
|
+
children: status === "submitted" ? "Submitted" : status === "approved" ? "Approved" : "Submit calibration"
|
|
9115
|
+
}
|
|
9116
|
+
)
|
|
9117
|
+
] })
|
|
9118
|
+
]
|
|
9119
|
+
}
|
|
9120
|
+
);
|
|
9121
|
+
}
|
|
9122
|
+
|
|
9123
|
+
// src/components/event-calendar/types.ts
|
|
9124
|
+
var DEFAULT_WORKING_HOURS = {
|
|
9125
|
+
0: { from: 0, to: 0 },
|
|
9126
|
+
// Sunday - closed
|
|
9127
|
+
1: { from: 9, to: 17 },
|
|
9128
|
+
// Monday
|
|
9129
|
+
2: { from: 9, to: 17 },
|
|
9130
|
+
// Tuesday
|
|
9131
|
+
3: { from: 9, to: 17 },
|
|
9132
|
+
// Wednesday
|
|
9133
|
+
4: { from: 9, to: 17 },
|
|
9134
|
+
// Thursday
|
|
9135
|
+
5: { from: 9, to: 17 },
|
|
9136
|
+
// Friday
|
|
9137
|
+
6: { from: 0, to: 0 }
|
|
9138
|
+
// Saturday - closed
|
|
9139
|
+
};
|
|
9140
|
+
var DEFAULT_VISIBLE_HOURS = { from: 0, to: 24 };
|
|
9141
|
+
var EVENT_COLORS = {
|
|
9142
|
+
blue: {
|
|
9143
|
+
bg: "bg-blue-500/20",
|
|
9144
|
+
text: "text-blue-700 dark:text-blue-300",
|
|
9145
|
+
border: "border-blue-500"
|
|
9146
|
+
},
|
|
9147
|
+
green: {
|
|
9148
|
+
bg: "bg-green-500/20",
|
|
9149
|
+
text: "text-green-700 dark:text-green-300",
|
|
9150
|
+
border: "border-green-500"
|
|
9151
|
+
},
|
|
9152
|
+
red: {
|
|
9153
|
+
bg: "bg-red-500/20",
|
|
9154
|
+
text: "text-red-700 dark:text-red-300",
|
|
9155
|
+
border: "border-red-500"
|
|
9156
|
+
},
|
|
9157
|
+
yellow: {
|
|
9158
|
+
bg: "bg-yellow-500/20",
|
|
9159
|
+
text: "text-yellow-700 dark:text-yellow-300",
|
|
9160
|
+
border: "border-yellow-500"
|
|
9161
|
+
},
|
|
9162
|
+
purple: {
|
|
9163
|
+
bg: "bg-purple-500/20",
|
|
9164
|
+
text: "text-purple-700 dark:text-purple-300",
|
|
9165
|
+
border: "border-purple-500"
|
|
9166
|
+
},
|
|
9167
|
+
orange: {
|
|
9168
|
+
bg: "bg-primary/20",
|
|
9169
|
+
text: "text-primary dark:text-orange-300",
|
|
9170
|
+
border: "border-primary"
|
|
9171
|
+
}
|
|
9172
|
+
};
|
|
9173
|
+
var VIEW_LABELS = {
|
|
9174
|
+
month: "Month",
|
|
9175
|
+
week: "Week",
|
|
9176
|
+
day: "Day",
|
|
9177
|
+
year: "Year",
|
|
9178
|
+
agenda: "Agenda"
|
|
9179
|
+
};
|
|
9180
|
+
var BADGE_VARIANT_LABELS = {
|
|
9181
|
+
dot: "Dot",
|
|
9182
|
+
colored: "Colored",
|
|
9183
|
+
mixed: "Mixed"
|
|
9184
|
+
};
|
|
9185
|
+
var CalendarContext = React22.createContext(null);
|
|
9186
|
+
function EventCalendarProvider({
|
|
9187
|
+
children,
|
|
9188
|
+
events: initialEvents = [],
|
|
9189
|
+
users: initialUsers = [],
|
|
9190
|
+
defaultDate = /* @__PURE__ */ new Date(),
|
|
9191
|
+
defaultView = "month",
|
|
9192
|
+
defaultBadgeVariant = "colored",
|
|
9193
|
+
defaultUserId = null,
|
|
5922
9194
|
defaultWorkingHours = DEFAULT_WORKING_HOURS,
|
|
5923
9195
|
defaultVisibleHours = DEFAULT_VISIBLE_HOURS,
|
|
5924
9196
|
onEventAdd,
|
|
5925
9197
|
onEventUpdate,
|
|
5926
9198
|
onEventDelete
|
|
5927
9199
|
}) {
|
|
5928
|
-
const [selectedDate, setSelectedDate] =
|
|
5929
|
-
const [selectedUserId, setSelectedUserId] =
|
|
5930
|
-
const [events, setEventsState] =
|
|
5931
|
-
const [users] =
|
|
5932
|
-
const [badgeVariant, setBadgeVariant] =
|
|
5933
|
-
const [view, setView] =
|
|
5934
|
-
const [workingHours, setWorkingHours] =
|
|
5935
|
-
const [visibleHours, setVisibleHours] =
|
|
5936
|
-
|
|
9200
|
+
const [selectedDate, setSelectedDate] = React22.useState(defaultDate);
|
|
9201
|
+
const [selectedUserId, setSelectedUserId] = React22.useState(defaultUserId);
|
|
9202
|
+
const [events, setEventsState] = React22.useState(initialEvents);
|
|
9203
|
+
const [users] = React22.useState(initialUsers);
|
|
9204
|
+
const [badgeVariant, setBadgeVariant] = React22.useState(defaultBadgeVariant);
|
|
9205
|
+
const [view, setView] = React22.useState(defaultView);
|
|
9206
|
+
const [workingHours, setWorkingHours] = React22.useState(defaultWorkingHours);
|
|
9207
|
+
const [visibleHours, setVisibleHours] = React22.useState(defaultVisibleHours);
|
|
9208
|
+
React22.useEffect(() => {
|
|
5937
9209
|
setEventsState(initialEvents);
|
|
5938
9210
|
}, [initialEvents]);
|
|
5939
|
-
const setEvents =
|
|
9211
|
+
const setEvents = React22.useCallback((newEvents) => {
|
|
5940
9212
|
setEventsState(newEvents);
|
|
5941
9213
|
}, []);
|
|
5942
|
-
const addEvent =
|
|
9214
|
+
const addEvent = React22.useCallback((event) => {
|
|
5943
9215
|
setEventsState((prev) => [...prev, event]);
|
|
5944
9216
|
onEventAdd?.(event);
|
|
5945
9217
|
}, [onEventAdd]);
|
|
5946
|
-
const updateEvent =
|
|
9218
|
+
const updateEvent = React22.useCallback((event) => {
|
|
5947
9219
|
setEventsState(
|
|
5948
9220
|
(prev) => prev.map((e) => e.id === event.id ? event : e)
|
|
5949
9221
|
);
|
|
5950
9222
|
onEventUpdate?.(event);
|
|
5951
9223
|
}, [onEventUpdate]);
|
|
5952
|
-
const deleteEvent =
|
|
9224
|
+
const deleteEvent = React22.useCallback((eventId) => {
|
|
5953
9225
|
setEventsState((prev) => prev.filter((e) => e.id !== eventId));
|
|
5954
9226
|
onEventDelete?.(eventId);
|
|
5955
9227
|
}, [onEventDelete]);
|
|
5956
|
-
const goToToday =
|
|
9228
|
+
const goToToday = React22.useCallback(() => {
|
|
5957
9229
|
setSelectedDate(/* @__PURE__ */ new Date());
|
|
5958
9230
|
}, []);
|
|
5959
|
-
const goToPrevious =
|
|
9231
|
+
const goToPrevious = React22.useCallback(() => {
|
|
5960
9232
|
setSelectedDate((current) => {
|
|
5961
9233
|
switch (view) {
|
|
5962
9234
|
case "day":
|
|
@@ -5974,7 +9246,7 @@ function EventCalendarProvider({
|
|
|
5974
9246
|
}
|
|
5975
9247
|
});
|
|
5976
9248
|
}, [view]);
|
|
5977
|
-
const goToNext =
|
|
9249
|
+
const goToNext = React22.useCallback(() => {
|
|
5978
9250
|
setSelectedDate((current) => {
|
|
5979
9251
|
switch (view) {
|
|
5980
9252
|
case "day":
|
|
@@ -5992,7 +9264,7 @@ function EventCalendarProvider({
|
|
|
5992
9264
|
}
|
|
5993
9265
|
});
|
|
5994
9266
|
}, [view]);
|
|
5995
|
-
const contextValue =
|
|
9267
|
+
const contextValue = React22.useMemo(
|
|
5996
9268
|
() => ({
|
|
5997
9269
|
// State
|
|
5998
9270
|
selectedDate,
|
|
@@ -6039,7 +9311,7 @@ function EventCalendarProvider({
|
|
|
6039
9311
|
return /* @__PURE__ */ jsx(CalendarContext.Provider, { value: contextValue, children });
|
|
6040
9312
|
}
|
|
6041
9313
|
function useEventCalendar() {
|
|
6042
|
-
const context =
|
|
9314
|
+
const context = React22.useContext(CalendarContext);
|
|
6043
9315
|
if (!context) {
|
|
6044
9316
|
throw new Error("useEventCalendar must be used within an EventCalendarProvider");
|
|
6045
9317
|
}
|
|
@@ -6047,14 +9319,14 @@ function useEventCalendar() {
|
|
|
6047
9319
|
}
|
|
6048
9320
|
function useFilteredEvents() {
|
|
6049
9321
|
const { events, selectedUserId } = useEventCalendar();
|
|
6050
|
-
return
|
|
9322
|
+
return React22.useMemo(() => {
|
|
6051
9323
|
if (!selectedUserId) return events;
|
|
6052
9324
|
return events.filter((event) => event.user.id === selectedUserId);
|
|
6053
9325
|
}, [events, selectedUserId]);
|
|
6054
9326
|
}
|
|
6055
9327
|
function useEventsInRange(startDate, endDate) {
|
|
6056
9328
|
const filteredEvents = useFilteredEvents();
|
|
6057
|
-
return
|
|
9329
|
+
return React22.useMemo(() => {
|
|
6058
9330
|
return filteredEvents.filter((event) => {
|
|
6059
9331
|
const eventStart = new Date(event.startDate);
|
|
6060
9332
|
const eventEnd = new Date(event.endDate);
|
|
@@ -6428,7 +9700,7 @@ function getViewDateRange(date, view) {
|
|
|
6428
9700
|
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6429
9701
|
}
|
|
6430
9702
|
}
|
|
6431
|
-
function
|
|
9703
|
+
function formatDateRange2(start, end) {
|
|
6432
9704
|
if (isSameDay(start, end)) {
|
|
6433
9705
|
return format(start, "MMM d, yyyy");
|
|
6434
9706
|
}
|
|
@@ -6612,8 +9884,8 @@ function MoreEvents({ count, onClick, className }) {
|
|
|
6612
9884
|
);
|
|
6613
9885
|
}
|
|
6614
9886
|
function TimeIndicator({ className }) {
|
|
6615
|
-
const [now, setNow] =
|
|
6616
|
-
|
|
9887
|
+
const [now, setNow] = React22.useState(/* @__PURE__ */ new Date());
|
|
9888
|
+
React22.useEffect(() => {
|
|
6617
9889
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
6618
9890
|
return () => clearInterval(interval);
|
|
6619
9891
|
}, []);
|
|
@@ -6650,24 +9922,24 @@ function DateBadge({ date, className }) {
|
|
|
6650
9922
|
}
|
|
6651
9923
|
);
|
|
6652
9924
|
}
|
|
6653
|
-
var DragContext =
|
|
9925
|
+
var DragContext = React22.createContext(null);
|
|
6654
9926
|
function DragProvider({
|
|
6655
9927
|
children,
|
|
6656
9928
|
snapMinutes = 15,
|
|
6657
9929
|
onDragStart,
|
|
6658
9930
|
onDragEnd
|
|
6659
9931
|
}) {
|
|
6660
|
-
const [draggedEvent, setDraggedEventState] =
|
|
6661
|
-
const [isDragging, setIsDragging] =
|
|
9932
|
+
const [draggedEvent, setDraggedEventState] = React22.useState(null);
|
|
9933
|
+
const [isDragging, setIsDragging] = React22.useState(false);
|
|
6662
9934
|
const { updateEvent } = useEventCalendar();
|
|
6663
|
-
const setDraggedEvent =
|
|
9935
|
+
const setDraggedEvent = React22.useCallback((event) => {
|
|
6664
9936
|
setDraggedEventState(event);
|
|
6665
9937
|
setIsDragging(!!event);
|
|
6666
9938
|
if (event) {
|
|
6667
9939
|
onDragStart?.(event);
|
|
6668
9940
|
}
|
|
6669
9941
|
}, [onDragStart]);
|
|
6670
|
-
const handleDrop =
|
|
9942
|
+
const handleDrop = React22.useCallback((newStartDate) => {
|
|
6671
9943
|
if (!draggedEvent) return;
|
|
6672
9944
|
const snappedDate = snapToInterval(newStartDate, snapMinutes);
|
|
6673
9945
|
const { startDate, endDate } = calculateDropDates(draggedEvent, snappedDate);
|
|
@@ -6680,7 +9952,7 @@ function DragProvider({
|
|
|
6680
9952
|
onDragEnd?.(updatedEvent, new Date(startDate), new Date(endDate));
|
|
6681
9953
|
setDraggedEvent(null);
|
|
6682
9954
|
}, [draggedEvent, snapMinutes, updateEvent, onDragEnd, setDraggedEvent]);
|
|
6683
|
-
const contextValue =
|
|
9955
|
+
const contextValue = React22.useMemo(
|
|
6684
9956
|
() => ({
|
|
6685
9957
|
draggedEvent,
|
|
6686
9958
|
setDraggedEvent,
|
|
@@ -6691,7 +9963,7 @@ function DragProvider({
|
|
|
6691
9963
|
return /* @__PURE__ */ jsx(DragContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(DragDropHandler, { onDrop: handleDrop, children }) });
|
|
6692
9964
|
}
|
|
6693
9965
|
function useDrag() {
|
|
6694
|
-
const context =
|
|
9966
|
+
const context = React22.useContext(DragContext);
|
|
6695
9967
|
if (!context) {
|
|
6696
9968
|
throw new Error("useDrag must be used within a DragProvider");
|
|
6697
9969
|
}
|
|
@@ -6736,7 +10008,7 @@ function DroppableZone({
|
|
|
6736
10008
|
}) {
|
|
6737
10009
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6738
10010
|
const { updateEvent } = useEventCalendar();
|
|
6739
|
-
const [isOver, setIsOver] =
|
|
10011
|
+
const [isOver, setIsOver] = React22.useState(false);
|
|
6740
10012
|
const handleDragOver = (e) => {
|
|
6741
10013
|
e.preventDefault();
|
|
6742
10014
|
e.dataTransfer.dropEffect = "move";
|
|
@@ -6774,23 +10046,23 @@ function DroppableZone({
|
|
|
6774
10046
|
function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
6775
10047
|
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6776
10048
|
const { updateEvent } = useEventCalendar();
|
|
6777
|
-
const [isOver, setIsOver] =
|
|
6778
|
-
const dropTargetDate =
|
|
10049
|
+
const [isOver, setIsOver] = React22.useState(false);
|
|
10050
|
+
const dropTargetDate = React22.useMemo(() => {
|
|
6779
10051
|
const targetDate = new Date(date);
|
|
6780
10052
|
if (hour !== void 0) {
|
|
6781
10053
|
targetDate.setHours(hour, minute, 0, 0);
|
|
6782
10054
|
}
|
|
6783
10055
|
return targetDate;
|
|
6784
10056
|
}, [date, hour, minute]);
|
|
6785
|
-
const handleDragOver =
|
|
10057
|
+
const handleDragOver = React22.useCallback((e) => {
|
|
6786
10058
|
e.preventDefault();
|
|
6787
10059
|
e.dataTransfer.dropEffect = "move";
|
|
6788
10060
|
if (!isOver) setIsOver(true);
|
|
6789
10061
|
}, [isOver]);
|
|
6790
|
-
const handleDragLeave =
|
|
10062
|
+
const handleDragLeave = React22.useCallback(() => {
|
|
6791
10063
|
setIsOver(false);
|
|
6792
10064
|
}, []);
|
|
6793
|
-
const handleDrop =
|
|
10065
|
+
const handleDrop = React22.useCallback((e) => {
|
|
6794
10066
|
e.preventDefault();
|
|
6795
10067
|
setIsOver(false);
|
|
6796
10068
|
if (!draggedEvent) return;
|
|
@@ -6817,13 +10089,13 @@ function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
|
6817
10089
|
function useDraggable(event, disabled = false) {
|
|
6818
10090
|
const { setDraggedEvent, draggedEvent } = useDrag();
|
|
6819
10091
|
const isDragged = draggedEvent?.id === event.id;
|
|
6820
|
-
const handleDragStart =
|
|
10092
|
+
const handleDragStart = React22.useCallback((e) => {
|
|
6821
10093
|
if (disabled) return;
|
|
6822
10094
|
e.dataTransfer.effectAllowed = "move";
|
|
6823
10095
|
e.dataTransfer.setData("text/plain", event.id);
|
|
6824
10096
|
setDraggedEvent(event);
|
|
6825
10097
|
}, [disabled, event, setDraggedEvent]);
|
|
6826
|
-
const handleDragEnd =
|
|
10098
|
+
const handleDragEnd = React22.useCallback(() => {
|
|
6827
10099
|
setDraggedEvent(null);
|
|
6828
10100
|
}, [setDraggedEvent]);
|
|
6829
10101
|
return {
|
|
@@ -6864,15 +10136,15 @@ function MonthView({
|
|
|
6864
10136
|
}) {
|
|
6865
10137
|
const { selectedDate, badgeVariant, setSelectedDate, setView } = useEventCalendar();
|
|
6866
10138
|
const filteredEvents = useFilteredEvents();
|
|
6867
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10139
|
+
const { singleDayEvents, multiDayEvents } = React22.useMemo(
|
|
6868
10140
|
() => splitEventsByDuration(filteredEvents),
|
|
6869
10141
|
[filteredEvents]
|
|
6870
10142
|
);
|
|
6871
|
-
const cells =
|
|
10143
|
+
const cells = React22.useMemo(
|
|
6872
10144
|
() => getCalendarCells(selectedDate),
|
|
6873
10145
|
[selectedDate]
|
|
6874
10146
|
);
|
|
6875
|
-
const eventPositions =
|
|
10147
|
+
const eventPositions = React22.useMemo(
|
|
6876
10148
|
() => calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate),
|
|
6877
10149
|
[multiDayEvents, singleDayEvents, selectedDate]
|
|
6878
10150
|
);
|
|
@@ -7054,7 +10326,7 @@ function WeekView({
|
|
|
7054
10326
|
visibleHours
|
|
7055
10327
|
} = useEventCalendar();
|
|
7056
10328
|
const filteredEvents = useFilteredEvents();
|
|
7057
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10329
|
+
const { singleDayEvents, multiDayEvents } = React22.useMemo(
|
|
7058
10330
|
() => splitEventsByDuration(filteredEvents),
|
|
7059
10331
|
[filteredEvents]
|
|
7060
10332
|
);
|
|
@@ -7260,8 +10532,8 @@ function CalendarTimeline({
|
|
|
7260
10532
|
firstVisibleHour,
|
|
7261
10533
|
lastVisibleHour
|
|
7262
10534
|
}) {
|
|
7263
|
-
const [currentTime, setCurrentTime] =
|
|
7264
|
-
|
|
10535
|
+
const [currentTime, setCurrentTime] = React22.useState(/* @__PURE__ */ new Date());
|
|
10536
|
+
React22.useEffect(() => {
|
|
7265
10537
|
const interval = setInterval(() => {
|
|
7266
10538
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7267
10539
|
}, 6e4);
|
|
@@ -7344,7 +10616,7 @@ function DayView({
|
|
|
7344
10616
|
visibleHours
|
|
7345
10617
|
} = useEventCalendar();
|
|
7346
10618
|
const filteredEvents = useFilteredEvents();
|
|
7347
|
-
const { singleDayEvents, multiDayEvents } =
|
|
10619
|
+
const { singleDayEvents, multiDayEvents } = React22.useMemo(
|
|
7348
10620
|
() => splitEventsByDuration(filteredEvents),
|
|
7349
10621
|
[filteredEvents]
|
|
7350
10622
|
);
|
|
@@ -7352,7 +10624,7 @@ function DayView({
|
|
|
7352
10624
|
visibleHours,
|
|
7353
10625
|
singleDayEvents
|
|
7354
10626
|
);
|
|
7355
|
-
const currentEvents =
|
|
10627
|
+
const currentEvents = React22.useMemo(() => {
|
|
7356
10628
|
if (!isToday(selectedDate)) return [];
|
|
7357
10629
|
return getCurrentEvents(singleDayEvents);
|
|
7358
10630
|
}, [singleDayEvents, selectedDate]);
|
|
@@ -7576,8 +10848,8 @@ function CalendarTimeline2({
|
|
|
7576
10848
|
firstVisibleHour,
|
|
7577
10849
|
lastVisibleHour
|
|
7578
10850
|
}) {
|
|
7579
|
-
const [currentTime, setCurrentTime] =
|
|
7580
|
-
|
|
10851
|
+
const [currentTime, setCurrentTime] = React22.useState(/* @__PURE__ */ new Date());
|
|
10852
|
+
React22.useEffect(() => {
|
|
7581
10853
|
const interval = setInterval(() => {
|
|
7582
10854
|
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7583
10855
|
}, 6e4);
|
|
@@ -7611,7 +10883,7 @@ function YearView({
|
|
|
7611
10883
|
}) {
|
|
7612
10884
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7613
10885
|
const filteredEvents = useFilteredEvents();
|
|
7614
|
-
const months =
|
|
10886
|
+
const months = React22.useMemo(() => {
|
|
7615
10887
|
const yearStart = startOfYear(selectedDate);
|
|
7616
10888
|
return Array.from({ length: 12 }, (_, i) => addMonths(yearStart, i));
|
|
7617
10889
|
}, [selectedDate]);
|
|
@@ -7734,11 +11006,11 @@ function AgendaView({
|
|
|
7734
11006
|
}) {
|
|
7735
11007
|
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7736
11008
|
const filteredEvents = useFilteredEvents();
|
|
7737
|
-
const { singleDayEvents, multiDayEvents } =
|
|
11009
|
+
const { singleDayEvents, multiDayEvents } = React22.useMemo(
|
|
7738
11010
|
() => splitEventsByDuration(filteredEvents),
|
|
7739
11011
|
[filteredEvents]
|
|
7740
11012
|
);
|
|
7741
|
-
const eventsByDay =
|
|
11013
|
+
const eventsByDay = React22.useMemo(() => {
|
|
7742
11014
|
const allDates = /* @__PURE__ */ new Map();
|
|
7743
11015
|
singleDayEvents.forEach((event) => {
|
|
7744
11016
|
const eventDate = parseISO(event.startDate);
|
|
@@ -7931,7 +11203,7 @@ function CalendarHeader({
|
|
|
7931
11203
|
const filteredEvents = useFilteredEvents();
|
|
7932
11204
|
const eventCount = filteredEvents.length;
|
|
7933
11205
|
const { start: rangeStart, end: rangeEnd } = getViewDateRange(selectedDate, view);
|
|
7934
|
-
const dateRangeLabel =
|
|
11206
|
+
const dateRangeLabel = formatDateRange2(rangeStart, rangeEnd);
|
|
7935
11207
|
const getInitials = (name) => {
|
|
7936
11208
|
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7937
11209
|
};
|
|
@@ -8203,16 +11475,16 @@ function EventDialog({
|
|
|
8203
11475
|
defaultUserId
|
|
8204
11476
|
}) {
|
|
8205
11477
|
const { addEvent, updateEvent, deleteEvent, users } = useEventCalendar();
|
|
8206
|
-
const [title, setTitle] =
|
|
8207
|
-
const [description, setDescription] =
|
|
8208
|
-
const [startDate, setStartDate] =
|
|
8209
|
-
const [startTime, setStartTime] =
|
|
8210
|
-
const [endDate, setEndDate] =
|
|
8211
|
-
const [endTime, setEndTime] =
|
|
8212
|
-
const [color, setColor] =
|
|
8213
|
-
const [userId, setUserId] =
|
|
8214
|
-
const [isSubmitting, setIsSubmitting] =
|
|
8215
|
-
|
|
11478
|
+
const [title, setTitle] = React22.useState("");
|
|
11479
|
+
const [description, setDescription] = React22.useState("");
|
|
11480
|
+
const [startDate, setStartDate] = React22.useState("");
|
|
11481
|
+
const [startTime, setStartTime] = React22.useState("");
|
|
11482
|
+
const [endDate, setEndDate] = React22.useState("");
|
|
11483
|
+
const [endTime, setEndTime] = React22.useState("");
|
|
11484
|
+
const [color, setColor] = React22.useState("blue");
|
|
11485
|
+
const [userId, setUserId] = React22.useState("");
|
|
11486
|
+
const [isSubmitting, setIsSubmitting] = React22.useState(false);
|
|
11487
|
+
React22.useEffect(() => {
|
|
8216
11488
|
if (open) {
|
|
8217
11489
|
if (mode === "edit" && event) {
|
|
8218
11490
|
const start = parseISO(event.startDate);
|
|
@@ -8435,7 +11707,7 @@ function QuickAddEvent({
|
|
|
8435
11707
|
onOpenDialog,
|
|
8436
11708
|
onClose
|
|
8437
11709
|
}) {
|
|
8438
|
-
const [title, setTitle] =
|
|
11710
|
+
const [title, setTitle] = React22.useState("");
|
|
8439
11711
|
const { users } = useEventCalendar();
|
|
8440
11712
|
const handleSubmit = (e) => {
|
|
8441
11713
|
e.preventDefault();
|
|
@@ -8502,8 +11774,8 @@ var HOUR_OPTIONS = Array.from({ length: 25 }, (_, i) => {
|
|
|
8502
11774
|
});
|
|
8503
11775
|
function ChangeVisibleHoursInput() {
|
|
8504
11776
|
const { visibleHours, setVisibleHours } = useEventCalendar();
|
|
8505
|
-
const [from, setFrom] =
|
|
8506
|
-
const [to, setTo] =
|
|
11777
|
+
const [from, setFrom] = React22.useState(visibleHours.from);
|
|
11778
|
+
const [to, setTo] = React22.useState(visibleHours.to);
|
|
8507
11779
|
const handleApply = () => {
|
|
8508
11780
|
const toHour = to === 0 ? 24 : to;
|
|
8509
11781
|
setVisibleHours({ from, to: toHour });
|
|
@@ -8549,7 +11821,7 @@ var HOUR_OPTIONS2 = Array.from({ length: 25 }, (_, i) => {
|
|
|
8549
11821
|
});
|
|
8550
11822
|
function ChangeWorkingHoursInput() {
|
|
8551
11823
|
const { workingHours, setWorkingHours } = useEventCalendar();
|
|
8552
|
-
const [localWorkingHours, setLocalWorkingHours] =
|
|
11824
|
+
const [localWorkingHours, setLocalWorkingHours] = React22.useState({
|
|
8553
11825
|
...workingHours
|
|
8554
11826
|
});
|
|
8555
11827
|
const handleToggleDay = (dayId) => {
|
|
@@ -8698,8 +11970,8 @@ function CalendarSettingsButton({
|
|
|
8698
11970
|
);
|
|
8699
11971
|
}
|
|
8700
11972
|
function useMediaQuery(query) {
|
|
8701
|
-
const [matches, setMatches] =
|
|
8702
|
-
|
|
11973
|
+
const [matches, setMatches] = React22.useState(false);
|
|
11974
|
+
React22.useEffect(() => {
|
|
8703
11975
|
const media = window.matchMedia(query);
|
|
8704
11976
|
setMatches(media.matches);
|
|
8705
11977
|
const listener = (event) => {
|
|
@@ -8751,11 +12023,11 @@ function BigCalendarInner({
|
|
|
8751
12023
|
maxEventsPerDay
|
|
8752
12024
|
}) {
|
|
8753
12025
|
const { view, setView } = useEventCalendar();
|
|
8754
|
-
const [dialogOpen, setDialogOpen] =
|
|
8755
|
-
const [settingsDialogOpen, setSettingsDialogOpen] =
|
|
8756
|
-
const [selectedEvent, setSelectedEvent] =
|
|
8757
|
-
const [dialogMode, setDialogMode] =
|
|
8758
|
-
const [defaultDate, setDefaultDate] =
|
|
12026
|
+
const [dialogOpen, setDialogOpen] = React22.useState(false);
|
|
12027
|
+
const [settingsDialogOpen, setSettingsDialogOpen] = React22.useState(false);
|
|
12028
|
+
const [selectedEvent, setSelectedEvent] = React22.useState(null);
|
|
12029
|
+
const [dialogMode, setDialogMode] = React22.useState("add");
|
|
12030
|
+
const [defaultDate, setDefaultDate] = React22.useState(/* @__PURE__ */ new Date());
|
|
8759
12031
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
8760
12032
|
const isCompact = compact === "auto" ? isMobile : compact;
|
|
8761
12033
|
const handleAddClick = () => {
|
|
@@ -8914,6 +12186,6 @@ function CalendarView({
|
|
|
8914
12186
|
}
|
|
8915
12187
|
}
|
|
8916
12188
|
|
|
8917
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AgendaView, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Avatar, AvatarFallback, AvatarImage, BADGE_VARIANT_LABELS, Badge, BigCalendar, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarContext, CalendarDayButton, CalendarHeader, CalendarHeaderCompact, CalendarSettingsButton, CalendarSettingsContent, CalendarSettingsDialog, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChangeBadgeVariantInput, ChangeVisibleHoursInput, ChangeWorkingHoursInput, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DEFAULT_VISIBLE_HOURS, DEFAULT_WORKING_HOURS, DateBadge, DayView, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DragContext, DragProvider, DraggableEvent, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DroppableZone, EVENT_COLORS, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EventBadge, EventCalendarProvider, EventDialog, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Item6 as Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label2 as Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MonthView, MoreEvents, NativeSelect, NativeSelectOptGroup, NativeSelectOption, NavMain, NavProjects, NavSecondary, NavUser, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PlayerCanvas, PlayerCanvasActionButton, PlayerCanvasControls, PlayerCanvasDivider, PlayerCanvasInfo, PlayerCanvasLabel, PlayerCanvasPlayButton, PlayerCanvasProgress, PlayerCanvasSkipButton, PlayerCanvasTitle, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, QuickAddEvent, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, SearchForm, SearchTrigger, Section, SectionContent, SectionDescription, SectionFooter, SectionHeader, SectionTitle, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiteHeader, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeSwitch, TimeIndicator, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolBarCanvas, ToolBarCanvasButton, ToolBarCanvasDivider, ToolBarCanvasGroup, Tooltip2 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserAvatarsDropdown, VIEW_LABELS, WeekView, YearView, badgeVariants, buttonGroupVariants, buttonVariants, calculateDropDates, calculateMonthEventPositions, cardVariants, createDefaultEvent, formatDateRange, formatTime, generateEventId, getCalendarCells, getCurrentEvents, getDayHours, getEventBlockStyle, getEventDuration, getEventDurationMinutes, getEventsCount, getEventsForDate, getEventsInRange, getHeaderLabel, getMonthCellEvents, getMonthDays, getTimeHeight, getTimePosition, getViewDateRange, getVisibleHours, getWeekDayNames, getWeekDays, getYearMonths, groupEvents, isMultiDayEvent, isWorkingHour, navigateDate, navigationMenuTriggerStyle, playerCanvasPlayButtonVariants, playerCanvasSkipButtonVariants, rangeText, sectionVariants, snapToInterval, sortEvents, splitEventsByDuration, toggleVariants, toolBarCanvasButtonVariants, useDrag, useDraggable, useDroppable, useEventCalendar, useEventsInRange, useFilteredEvents, useFormField, useIsMobile, useSearchShortcut, useSidebar };
|
|
12189
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AgendaView, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Avatar, AvatarFallback, AvatarImage, BADGE_VARIANT_LABELS, Badge, BigCalendar, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarContext, CalendarDayButton, CalendarHeader, CalendarHeaderCompact, CalendarSettingsButton, CalendarSettingsContent, CalendarSettingsDialog, CalibrationTable, CalibrationWeekCell, CalibrationWeekHeader, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChangeBadgeVariantInput, ChangeVisibleHoursInput, ChangeWorkingHoursInput, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, CircularProgress, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CommentButton, CommentDialog, CommentPopover, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DEFAULT_VISIBLE_HOURS, DEFAULT_WORKING_HOURS, DataTableColumnHeader, DataTablePagination, DataTableViewOptions, DateBadge, DayView, DeliveryIndicator, DeliveryIndicators, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DragContext, DragProvider, DraggableEvent, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DroppableZone, EVENT_COLORS, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EventBadge, EventCalendarProvider, EventDialog, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Item6 as Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label2 as Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MonthView, MoreEvents, NativeSelect, NativeSelectOptGroup, NativeSelectOption, NavMain, NavProjects, NavSecondary, NavUser, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NetBadge, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PlanningTable, PlanningTableToolbar, PlanningWeekCommentPopover, PlayerCanvas, PlayerCanvasActionButton, PlayerCanvasControls, PlayerCanvasDivider, PlayerCanvasInfo, PlayerCanvasLabel, PlayerCanvasPlayButton, PlayerCanvasProgress, PlayerCanvasSkipButton, PlayerCanvasTitle, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, QuickAddEvent, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, RowHeaderCell, ScrollArea, ScrollBar, SearchForm, SearchTrigger, Section, SectionContent, SectionDescription, SectionFooter, SectionHeader, SectionTitle, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiteHeader, Skeleton, Slider, Spinner, SubmitCalibrationBar, SupplierCell, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeSwitch, TimeIndicator, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolBarCanvas, ToolBarCanvasButton, ToolBarCanvasDivider, ToolBarCanvasGroup, Tooltip2 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserAvatarsDropdown, VIEW_LABELS, WeekCell, WeekDetailDialog, WeekHeader, WeekView, YearView, badgeVariants, buttonGroupVariants, buttonVariants, calculateCalibrationCells, calculateDropDates, calculateMonthEventPositions, canSubmitCalibration, cardVariants, createDefaultEvent, deliveryIndicatorVariants, formatCalibrationUnit, formatDateRange2 as formatDateRange, formatProductionUnit, formatTime, generateColumns, generateEventId, generateLocationOptions, generateWeekColumns, generateWeeks, getCalendarCells, getCommentLocationLabel, getCurrentEvents, getDayHours, getElementShipmentStatus, getEventBlockStyle, getEventDuration, getEventDurationMinutes, getEventsCount, getEventsForDate, getEventsInRange, getHeaderLabel, getISOWeek, getMonthCellEvents, getMonthDays, getShipmentStatusLabel, getSupplierColumn, getTimeHeight, getTimePosition, getViewDateRange, getVisibleHours, getWeekDayNames, getWeekDays, getWeekKey, getYearMonths, groupEvents, isMultiDayEvent, isWorkingHour, navigateDate, navigationMenuTriggerStyle, playerCanvasPlayButtonVariants, playerCanvasSkipButtonVariants, rangeText, sectionVariants, snapToInterval, sortEvents, splitEventsByDuration, toggleVariants, toolBarCanvasButtonVariants, useDrag, useDraggable, useDroppable, useEventCalendar, useEventsInRange, useFilteredEvents, useFormField, useIsMobile, useSearchShortcut, useSidebar };
|
|
8918
12190
|
//# sourceMappingURL=index.js.map
|
|
8919
12191
|
//# sourceMappingURL=index.js.map
|