@flowselections/pick-schermen-kwekers 1.0.2 → 1.0.3
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-lib/components/PickPublicPage.d.ts +7 -0
- package/dist-lib/components/PickPublicPage.d.ts.map +1 -0
- package/dist-lib/components/PickPublicPage.js +19 -0
- package/dist-lib/components/PickstationsPage.d.ts.map +1 -1
- package/dist-lib/components/PickstationsPage.js +57 -14
- package/dist-lib/components/pick/LanguageTiles.d.ts +8 -0
- package/dist-lib/components/pick/LanguageTiles.d.ts.map +1 -0
- package/dist-lib/components/pick/LanguageTiles.js +11 -0
- package/dist-lib/components/pick/PickScherm.d.ts +6 -4
- package/dist-lib/components/pick/PickScherm.d.ts.map +1 -1
- package/dist-lib/components/pick/PickScherm.js +145 -61
- package/dist-lib/components/pick/QueueTable.d.ts +4 -1
- package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
- package/dist-lib/components/pick/QueueTable.js +11 -10
- package/dist-lib/hooks/usePickQueue.d.ts +7 -1
- package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
- package/dist-lib/hooks/usePickQueue.js +43 -6
- package/dist-lib/index.d.ts +5 -6
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +6 -12
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +9245 -5437
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/layoutApi.d.ts +23 -0
- package/dist-lib/lib/layoutApi.d.ts.map +1 -0
- package/dist-lib/lib/layoutApi.js +94 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts +50 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.js +458 -0
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts +123 -0
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/documentTypes.js +74 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts +13 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.js +54 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts +196 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.js +813 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts +48 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.js +703 -0
- package/dist-lib/lib/layoutRenderer.d.ts +7 -0
- package/dist-lib/lib/layoutRenderer.d.ts.map +1 -0
- package/dist-lib/lib/layoutRenderer.js +233 -0
- package/dist-lib/lib/layoutTypes.d.ts +84 -0
- package/dist-lib/lib/layoutTypes.d.ts.map +1 -0
- package/dist-lib/lib/layoutTypes.js +25 -0
- package/dist-lib/lib/logisticsApi.d.ts +54 -0
- package/dist-lib/lib/logisticsApi.d.ts.map +1 -0
- package/dist-lib/lib/logisticsApi.js +72 -0
- package/dist-lib/lib/logisticsTypes.d.ts +34 -0
- package/dist-lib/lib/logisticsTypes.d.ts.map +1 -0
- package/dist-lib/lib/logisticsTypes.js +36 -0
- package/dist-lib/lib/orderContext.d.ts +50 -0
- package/dist-lib/lib/orderContext.d.ts.map +1 -0
- package/dist-lib/lib/orderContext.js +162 -0
- package/dist-lib/lib/pakbonOrderInput.d.ts +8 -0
- package/dist-lib/lib/pakbonOrderInput.d.ts.map +1 -0
- package/dist-lib/lib/pakbonOrderInput.js +150 -0
- package/dist-lib/lib/pickApi.d.ts +24 -1
- package/dist-lib/lib/pickApi.d.ts.map +1 -1
- package/dist-lib/lib/pickApi.js +46 -5
- package/dist-lib/lib/pickI18n.d.ts +14 -0
- package/dist-lib/lib/pickI18n.d.ts.map +1 -0
- package/dist-lib/lib/pickI18n.js +500 -0
- package/dist-lib/lib/pickPrint.d.ts +18 -0
- package/dist-lib/lib/pickPrint.d.ts.map +1 -0
- package/dist-lib/lib/pickPrint.js +184 -0
- package/dist-lib/lib/pickTypes.d.ts +1 -0
- package/dist-lib/lib/pickTypes.d.ts.map +1 -1
- package/package.json +5 -20
- package/dist-lib/components/PickBeheerPage.d.ts +0 -2
- package/dist-lib/components/PickBeheerPage.d.ts.map +0 -1
- package/dist-lib/components/PickBeheerPage.js +0 -84
- package/dist-lib/components/PickDashboardPage.d.ts +0 -2
- package/dist-lib/components/PickDashboardPage.d.ts.map +0 -1
- package/dist-lib/components/PickDashboardPage.js +0 -54
- package/dist-lib/components/PickKioskPage.d.ts +0 -7
- package/dist-lib/components/PickKioskPage.d.ts.map +0 -1
- package/dist-lib/components/PickKioskPage.js +0 -18
- package/dist-lib/components/PickstationDetailPage.d.ts +0 -6
- package/dist-lib/components/PickstationDetailPage.d.ts.map +0 -1
- package/dist-lib/components/PickstationDetailPage.js +0 -25
- package/dist-lib/components/pick/ConfigCrud.d.ts +0 -27
- package/dist-lib/components/pick/ConfigCrud.d.ts.map +0 -1
- package/dist-lib/components/pick/ConfigCrud.js +0 -64
- package/dist-lib/components/pick/CountryTiles.d.ts +0 -9
- package/dist-lib/components/pick/CountryTiles.d.ts.map +0 -1
- package/dist-lib/components/pick/CountryTiles.js +0 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickPublicPage.d.ts","sourceRoot":"","sources":["../../src/components/PickPublicPage.tsx"],"names":[],"mappings":"AAKA,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,+BA2B7C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { Loader2 } from "lucide-react";
|
|
4
|
+
import { pickApi } from "../lib/pickApi";
|
|
5
|
+
import { PickScherm } from "./pick/PickScherm";
|
|
6
|
+
/** Openbaar pickscherm, bereikbaar via /pickstation/<slug>. */
|
|
7
|
+
export function PickPublicPage({ slug }) {
|
|
8
|
+
const { data: station, isLoading } = useQuery({
|
|
9
|
+
queryKey: ["pick", "station", slug],
|
|
10
|
+
queryFn: () => pickApi.stationBySlug(slug),
|
|
11
|
+
});
|
|
12
|
+
if (isLoading) {
|
|
13
|
+
return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-background", children: _jsx(Loader2, { className: "h-8 w-8 animate-spin text-primary" }) }));
|
|
14
|
+
}
|
|
15
|
+
if (!station) {
|
|
16
|
+
return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-background", children: _jsx("p", { className: "text-muted-foreground", children: "Pickstation niet gevonden of niet actief." }) }));
|
|
17
|
+
}
|
|
18
|
+
return (_jsx("div", { className: "min-h-screen bg-background p-6", children: _jsx(PickScherm, { station: station }) }));
|
|
19
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,gBAAgB,gCAkL/B"}
|
|
@@ -1,18 +1,61 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { Button, Card, CardContent, Dialog, DialogContent, DialogHeader, DialogTitle, Input, Label, Switch, Textarea, toast, } from "@flowselections/core";
|
|
5
|
+
import { Copy, ExternalLink, Loader2, Pencil, Plus, Trash2 } from "lucide-react";
|
|
6
|
+
import { pickApi } from "../lib/pickApi";
|
|
7
|
+
import { usePickStations } from "../hooks/usePickConfig";
|
|
8
|
+
const emptyDraft = { name: "", description: "", active: true };
|
|
9
|
+
function publicUrl(slug) {
|
|
10
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
11
|
+
return `${origin}/pickstation/${slug ?? ""}`;
|
|
12
|
+
}
|
|
6
13
|
export function PickstationsPage() {
|
|
7
14
|
const { data: stations, isLoading } = usePickStations();
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const safeStations =
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const queryClient = useQueryClient();
|
|
16
|
+
const [draft, setDraft] = useState(null);
|
|
17
|
+
const safeStations = Array.isArray(stations) ? stations : [];
|
|
18
|
+
const save = useMutation({
|
|
19
|
+
mutationFn: async (d) => {
|
|
20
|
+
await pickApi.upsert("pick_stations", {
|
|
21
|
+
...(d.id ? { id: d.id } : {}),
|
|
22
|
+
name: d.name.trim(),
|
|
23
|
+
description: d.description.trim() || null,
|
|
24
|
+
active: d.active,
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
onSuccess: () => {
|
|
28
|
+
toast.success("Pickstation opgeslagen.");
|
|
29
|
+
setDraft(null);
|
|
30
|
+
queryClient.invalidateQueries({ queryKey: ["pick", "stations"] });
|
|
31
|
+
},
|
|
32
|
+
onError: (e) => toast.error(e instanceof Error ? e.message : "Opslaan mislukt."),
|
|
33
|
+
});
|
|
34
|
+
const remove = useMutation({
|
|
35
|
+
mutationFn: (id) => pickApi.remove("pick_stations", id),
|
|
36
|
+
onSuccess: () => {
|
|
37
|
+
toast.success("Pickstation verwijderd.");
|
|
38
|
+
queryClient.invalidateQueries({ queryKey: ["pick", "stations"] });
|
|
39
|
+
},
|
|
40
|
+
onError: (e) => toast.error(e instanceof Error ? e.message : "Verwijderen mislukt."),
|
|
41
|
+
});
|
|
42
|
+
const copyLink = async (station) => {
|
|
43
|
+
const url = publicUrl(station.slug);
|
|
44
|
+
try {
|
|
45
|
+
await navigator.clipboard.writeText(url);
|
|
46
|
+
toast.success("Link gekopieerd.");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
toast.error(url);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold text-foreground", children: "Pickstations" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer je pickstations en hun openbare link. Alle logica komt uit de Logistiek Engine." })] }), _jsxs(Button, { onClick: () => setDraft({ ...emptyDraft }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Nieuw pickstation"] })] }), isLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Laden..."] })) : safeStations.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen pickstations." })) : (_jsx("div", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: safeStations.map((station) => (_jsx(Card, { className: "border-2", children: _jsxs(CardContent, { className: "space-y-4 p-6", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: station.name }), _jsx("p", { className: "text-sm text-muted-foreground", children: station.description })] }), _jsx("span", { className: "rounded-full px-2 py-1 text-xs font-medium " +
|
|
53
|
+
(station.active
|
|
54
|
+
? "bg-primary/10 text-primary"
|
|
55
|
+
: "bg-muted text-muted-foreground"), children: station.active ? "Actief" : "Inactief" })] }), _jsx("code", { className: "block truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground", children: publicUrl(station.slug) }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { className: "flex-1", asChild: true, children: _jsxs("a", { href: publicUrl(station.slug), target: "_blank", rel: "noreferrer", children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), " Open pickstation"] }) }), _jsxs(Button, { variant: "outline", onClick: () => copyLink(station), children: [_jsx(Copy, { className: "mr-2 h-4 w-4" }), " Link kopi\u00EBren"] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setDraft({
|
|
56
|
+
id: station.id,
|
|
57
|
+
name: station.name,
|
|
58
|
+
description: station.description ?? "",
|
|
59
|
+
active: station.active,
|
|
60
|
+
}), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), " Wijzigen"] }), _jsxs(Button, { variant: "ghost", size: "sm", className: "text-destructive", onClick: () => remove.mutate(station.id), children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), " Verwijderen"] })] })] }) }, station.id))) })), _jsx(Dialog, { open: draft !== null, onOpenChange: (open) => !open && setDraft(null), children: _jsxs(DialogContent, { children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: draft?.id ? "Pickstation wijzigen" : "Nieuw pickstation" }) }), draft && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-name", children: "Naam" }), _jsx(Input, { id: "station-name", value: draft.name, onChange: (e) => setDraft({ ...draft, name: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-desc", children: "Omschrijving (optioneel)" }), _jsx(Textarea, { id: "station-desc", value: draft.description, onChange: (e) => setDraft({ ...draft, description: e.target.value }) })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md border px-3 py-2", children: [_jsx(Label, { htmlFor: "station-active", children: "Actief" }), _jsx(Switch, { id: "station-active", checked: draft.active, onCheckedChange: (v) => setDraft({ ...draft, active: v }) })] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => setDraft(null), children: "Annuleren" }), _jsxs(Button, { disabled: !draft.name.trim() || save.isPending, onClick: () => save.mutate(draft), children: [save.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), " Opslaan"] })] })] }))] }) })] }));
|
|
18
61
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
onSelect: (code: string) => void;
|
|
3
|
+
selected?: string | null;
|
|
4
|
+
}
|
|
5
|
+
/** Taalkeuze — zelfde tegel-uitstraling en bediening als de oude landselectie. */
|
|
6
|
+
export declare function LanguageTiles({ onSelect, selected }: Props): import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=LanguageTiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LanguageTiles.d.ts","sourceRoot":"","sources":["../../../src/components/pick/LanguageTiles.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAuB1D"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Card } from "@flowselections/core";
|
|
3
|
+
import { PICK_LANGUAGES } from "../../lib/pickI18n";
|
|
4
|
+
/** Taalkeuze — zelfde tegel-uitstraling en bediening als de oude landselectie. */
|
|
5
|
+
export function LanguageTiles({ onSelect, selected }) {
|
|
6
|
+
return (_jsx("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5", children: PICK_LANGUAGES.map((l) => (_jsxs(Card, { role: "button", tabIndex: 0, onClick: () => onSelect(l.code), onKeyDown: (e) => {
|
|
7
|
+
if (e.key === "Enter" || e.key === " ")
|
|
8
|
+
onSelect(l.code);
|
|
9
|
+
}, className: "cursor-pointer select-none border-2 p-6 text-center transition-all hover:border-primary hover:shadow-lg focus:border-primary focus:outline-none active:scale-[0.98] " +
|
|
10
|
+
(selected === l.code ? "border-primary bg-primary/5" : ""), children: [_jsx("div", { className: "text-5xl leading-none", children: l.flag }), _jsx("div", { className: "mt-3 text-lg font-semibold text-foreground", children: l.label })] }, l.code))) }));
|
|
11
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PickStation } from "../../lib/pickTypes";
|
|
2
2
|
interface Props {
|
|
3
3
|
station: PickStation;
|
|
4
|
-
screen: PickScreen;
|
|
5
4
|
onBack?: () => void;
|
|
6
|
-
kiosk?: boolean;
|
|
7
5
|
}
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Pickscherm. De Logistiek Engine bepaalt welke documenten zichtbaar zijn en
|
|
8
|
+
* in welke volgorde; dit scherm toont uitsluitend wat de wachtrij teruggeeft.
|
|
9
|
+
*/
|
|
10
|
+
export declare function PickScherm({ station, onBack }: Props): import("react").JSX.Element;
|
|
9
11
|
export {};
|
|
10
12
|
//# sourceMappingURL=PickScherm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUtE,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,+BAmVpD"}
|
|
@@ -1,114 +1,198 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useMemo, useState } from "react";
|
|
3
|
-
import { Badge, Button, Card, CardContent, Input,
|
|
4
|
-
import { ArrowLeft,
|
|
5
|
-
import {
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Badge, Button, Card, CardContent, Input, toast } from "@flowselections/core";
|
|
4
|
+
import { ArrowLeft, Globe, Loader2, Printer, RefreshCw, Search, WifiOff } from "lucide-react";
|
|
5
|
+
import { LanguageTiles } from "./LanguageTiles";
|
|
6
6
|
import { QueueTable } from "./QueueTable";
|
|
7
7
|
import { getSessionId, pickApi } from "../../lib/pickApi";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
8
|
+
import { completeLogisticsTaskForItem, documentTypeOf, EmptyLayoutError, MissingLayoutError, printQueueItem, } from "../../lib/pickPrint";
|
|
9
|
+
import { getPickTranslator } from "../../lib/pickI18n";
|
|
10
|
+
import { defaultFilters, usePickHeartbeat, usePickQueue, } from "../../hooks/usePickQueue";
|
|
11
|
+
import { usePickDocumentTypes, usePickStatuses } from "../../hooks/usePickConfig";
|
|
12
|
+
const LANG_STORAGE_KEY = "pick.language";
|
|
13
|
+
/**
|
|
14
|
+
* Pickscherm. De Logistiek Engine bepaalt welke documenten zichtbaar zijn en
|
|
15
|
+
* in welke volgorde; dit scherm toont uitsluitend wat de wachtrij teruggeeft.
|
|
16
|
+
*/
|
|
17
|
+
export function PickScherm({ station, onBack }) {
|
|
11
18
|
const sessionId = getSessionId();
|
|
12
|
-
const [
|
|
19
|
+
const [lang, setLang] = useState(null);
|
|
13
20
|
const [filters, setFilters] = useState(defaultFilters);
|
|
14
21
|
const [busyId, setBusyId] = useState(null);
|
|
15
|
-
const [
|
|
16
|
-
const
|
|
22
|
+
const [pending, setPending] = useState(null);
|
|
23
|
+
const autoFetched = useRef(false);
|
|
17
24
|
const { data: statuses } = usePickStatuses();
|
|
18
25
|
const { data: documentTypes } = usePickDocumentTypes();
|
|
19
|
-
const {
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const { online } = usePickHeartbeat(station.id, null, sessionId);
|
|
27
|
+
const t = useMemo(() => getPickTranslator(lang ?? "nl"), [lang]);
|
|
28
|
+
const layoutMissingMessage = useCallback((documentType) => t.lang === "nl"
|
|
29
|
+
? `Geen layout ingesteld voor ${documentType}. Stel deze in in de Layout maker (pakbonnen, verzendbrieven, extra).`
|
|
30
|
+
: `No layout configured for ${documentType}. Set it up in the Layout maker.`, [t]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (typeof window === "undefined")
|
|
33
|
+
return;
|
|
34
|
+
const stored = window.localStorage.getItem(LANG_STORAGE_KEY);
|
|
35
|
+
if (stored)
|
|
36
|
+
setLang(stored);
|
|
37
|
+
}, []);
|
|
38
|
+
const chooseLang = useCallback((code) => {
|
|
39
|
+
setLang(code);
|
|
40
|
+
if (typeof window !== "undefined")
|
|
41
|
+
window.localStorage.setItem(LANG_STORAGE_KEY, code);
|
|
42
|
+
}, []);
|
|
43
|
+
const effectiveFilters = useMemo(() => ({ ...filters, country: null, sortRules: [] }), [filters]);
|
|
44
|
+
const { items, total, loading, lockedIds, refresh, pendingCount, printedCount } = usePickQueue({
|
|
28
45
|
stationId: station.id,
|
|
29
|
-
screenId: screen.id,
|
|
30
46
|
filters: effectiveFilters,
|
|
31
|
-
enabled:
|
|
47
|
+
enabled: lang !== null,
|
|
32
48
|
});
|
|
33
|
-
const printerId = screen.printer_id ?? station.default_printer_id ?? null;
|
|
34
|
-
const printer = (Array.isArray(printers) ? printers : []).find((p) => p.id === printerId);
|
|
35
49
|
const runPrint = useCallback(async (item) => {
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
const printed = await printQueueItem(item, t.locale);
|
|
51
|
+
await pickApi.completePrint(item.id, null, sessionId);
|
|
52
|
+
await completeLogisticsTaskForItem(item, printed);
|
|
53
|
+
toast.success(`${item.document_number ?? t("document")} ${t("sentToPrinter")}`);
|
|
54
|
+
refresh();
|
|
55
|
+
}, [sessionId, refresh, t]);
|
|
56
|
+
/** Zet een printfout om in een begrijpelijke melding, zonder ooit zelf op te maken. */
|
|
57
|
+
const showPrintError = useCallback((e, item) => {
|
|
58
|
+
if (e instanceof EmptyLayoutError) {
|
|
59
|
+
toast.error(t.lang === "nl"
|
|
60
|
+
? `Layout heeft nog geen inhoud (${e.layoutName}).`
|
|
61
|
+
: `Layout has no content yet (${e.layoutName}).`);
|
|
38
62
|
return;
|
|
39
63
|
}
|
|
40
|
-
if (
|
|
41
|
-
toast.error(
|
|
42
|
-
await pickApi.releaseLock(item.id);
|
|
64
|
+
if (e instanceof MissingLayoutError) {
|
|
65
|
+
toast.error(layoutMissingMessage(e.documentType || documentTypeOf(item)));
|
|
43
66
|
return;
|
|
44
67
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
refresh();
|
|
48
|
-
}, [preview, printer, printerId, sessionId, refresh]);
|
|
68
|
+
toast.error(e instanceof Error ? e.message : t("notAvailable"));
|
|
69
|
+
}, [layoutMissingMessage, t]);
|
|
49
70
|
const handlePick = useCallback(async (item) => {
|
|
50
71
|
setBusyId(item.id);
|
|
51
72
|
try {
|
|
52
73
|
const claimed = await pickApi.claim({
|
|
53
74
|
itemId: item.id,
|
|
54
75
|
stationId: station.id,
|
|
55
|
-
screenId:
|
|
76
|
+
screenId: null,
|
|
56
77
|
sessionId,
|
|
57
|
-
timeout: station.lock_timeout_seconds,
|
|
78
|
+
timeout: station.lock_timeout_seconds ?? 120,
|
|
58
79
|
});
|
|
59
80
|
await runPrint(claimed ?? item);
|
|
60
81
|
}
|
|
61
82
|
catch (e) {
|
|
62
|
-
|
|
63
|
-
toast.error(message);
|
|
64
|
-
// Als claim wel is gelukt maar runPrint faalde, geef de lock vrij zodat
|
|
65
|
-
// het document niet minutenlang geblokkeerd blijft voor andere schermen.
|
|
83
|
+
showPrintError(e, item);
|
|
66
84
|
try {
|
|
67
85
|
await pickApi.releaseLock(item.id);
|
|
68
86
|
}
|
|
69
87
|
catch {
|
|
70
|
-
//
|
|
88
|
+
// lock al opgeruimd of van een andere sessie
|
|
71
89
|
}
|
|
72
90
|
refresh();
|
|
73
91
|
}
|
|
74
92
|
finally {
|
|
75
93
|
setBusyId(null);
|
|
76
94
|
}
|
|
77
|
-
}, [station.id, station.lock_timeout_seconds,
|
|
78
|
-
|
|
95
|
+
}, [station.id, station.lock_timeout_seconds, sessionId, runPrint, refresh, showPrintError]);
|
|
96
|
+
/** Vraagt de Logistiek Engine om de volgende opdracht en laat deze ter bevestiging zien. */
|
|
97
|
+
/** Print een al geprint document opnieuw, zonder de wachtrijstatus te wijzigen. */
|
|
98
|
+
const handleReprint = useCallback(async (item) => {
|
|
99
|
+
setBusyId(item.id);
|
|
100
|
+
try {
|
|
101
|
+
await printQueueItem(item, t.locale);
|
|
102
|
+
toast.success(`${item.document_number ?? t("document")} ${t("sentToPrinter")}`);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
showPrintError(e, item);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
setBusyId(null);
|
|
109
|
+
}
|
|
110
|
+
}, [t, showPrintError]);
|
|
111
|
+
const fetchNext = useCallback(async () => {
|
|
79
112
|
setBusyId("next");
|
|
80
|
-
let claimed = null;
|
|
81
113
|
try {
|
|
82
|
-
claimed = await pickApi.claimNext({
|
|
114
|
+
const claimed = await pickApi.claimNext({
|
|
83
115
|
stationId: station.id,
|
|
84
|
-
screenId:
|
|
85
|
-
country:
|
|
116
|
+
screenId: null,
|
|
117
|
+
country: null,
|
|
86
118
|
sessionId,
|
|
87
|
-
timeout: station.lock_timeout_seconds,
|
|
119
|
+
timeout: station.lock_timeout_seconds ?? 120,
|
|
88
120
|
});
|
|
89
|
-
|
|
121
|
+
if (!claimed)
|
|
122
|
+
throw new Error(t("noDocument"));
|
|
123
|
+
setPending(claimed);
|
|
124
|
+
return claimed;
|
|
90
125
|
}
|
|
91
126
|
catch (e) {
|
|
92
|
-
const message = e instanceof Error ? e.message : "
|
|
127
|
+
const message = e instanceof Error ? e.message : t("noDocument");
|
|
93
128
|
toast.error(message);
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
await pickApi.releaseLock(claimed.id);
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
// Negeren; lock wordt toch door heartbeat opgeruimd.
|
|
100
|
-
}
|
|
101
|
-
}
|
|
129
|
+
setPending(null);
|
|
102
130
|
refresh();
|
|
131
|
+
return null;
|
|
103
132
|
}
|
|
104
133
|
finally {
|
|
105
134
|
setBusyId(null);
|
|
106
135
|
}
|
|
107
|
-
}, [station.id, station.lock_timeout_seconds,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
136
|
+
}, [station.id, station.lock_timeout_seconds, sessionId, refresh, t]);
|
|
137
|
+
/** Bevestigt de opdracht, print deze en haalt direct de volgende op. */
|
|
138
|
+
const confirmPending = useCallback(async () => {
|
|
139
|
+
const item = pending;
|
|
140
|
+
if (!item)
|
|
141
|
+
return;
|
|
142
|
+
setBusyId("confirm");
|
|
143
|
+
try {
|
|
144
|
+
await runPrint(item);
|
|
145
|
+
setPending(null);
|
|
146
|
+
setBusyId(null);
|
|
147
|
+
await fetchNext();
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
showPrintError(e, item);
|
|
151
|
+
try {
|
|
152
|
+
await pickApi.releaseLock(item.id);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// heartbeat ruimt de lock alsnog op
|
|
156
|
+
}
|
|
157
|
+
setPending(null);
|
|
158
|
+
refresh();
|
|
159
|
+
setBusyId(null);
|
|
160
|
+
}
|
|
161
|
+
}, [pending, runPrint, fetchNext, refresh, showPrintError]);
|
|
162
|
+
const cancelPending = useCallback(async () => {
|
|
163
|
+
const item = pending;
|
|
164
|
+
setPending(null);
|
|
165
|
+
if (item) {
|
|
166
|
+
try {
|
|
167
|
+
await pickApi.releaseLock(item.id);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// lock verloopt automatisch
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
refresh();
|
|
174
|
+
}, [pending, refresh]);
|
|
175
|
+
/** Zet automatisch de volgende opdracht klaar, zodat één klik op printen volstaat. */
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
if (lang === null || loading)
|
|
178
|
+
return;
|
|
179
|
+
if (pending !== null || busyId !== null)
|
|
180
|
+
return;
|
|
181
|
+
if (autoFetched.current)
|
|
182
|
+
return;
|
|
183
|
+
if (items.length === 0)
|
|
184
|
+
return;
|
|
185
|
+
autoFetched.current = true;
|
|
186
|
+
void fetchNext();
|
|
187
|
+
}, [lang, loading, pending, busyId, items.length, fetchNext]);
|
|
188
|
+
/** Na een lege of mislukte poging opnieuw proberen zodra de wachtrij wijzigt. */
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
autoFetched.current = false;
|
|
191
|
+
}, [items.length]);
|
|
192
|
+
// Stap 1 — taalselectie
|
|
193
|
+
if (lang === null) {
|
|
194
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-2xl font-bold text-foreground", children: station.name }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("chooseLanguageHint") })] }), onBack && (_jsxs(Button, { variant: "outline", onClick: onBack, children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " ", t("back")] }))] }), _jsx(LanguageTiles, { onSelect: chooseLang })] }));
|
|
111
195
|
}
|
|
112
196
|
const totalPages = Math.max(1, Math.ceil(total / filters.pageSize));
|
|
113
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", onClick: () =>
|
|
197
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", onClick: () => setLang(null), children: [_jsx(Globe, { className: "mr-2 h-5 w-5" }), " ", t("changeLanguage")] }), _jsxs("div", { children: [_jsx("h2", { className: "text-xl font-bold text-foreground", children: station.name }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [pendingCount, " ", t("statusToPrint"), " \u00B7 ", printedCount, " ", t("statusPrinted")] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [!online && (_jsxs(Badge, { className: "bg-destructive text-destructive-foreground", children: [_jsx(WifiOff, { className: "mr-1 h-3.5 w-3.5" }), " ", t("offline")] })), _jsx(Button, { variant: "outline", size: "icon", onClick: refresh, "aria-label": t("refresh"), children: _jsx(RefreshCw, { className: "h-4 w-4" }) }), _jsxs(Button, { size: "lg", className: "h-14 px-8 text-lg", onClick: () => (pending ? confirmPending() : fetchNext()), disabled: busyId !== null, children: [busyId !== null ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] })] }), pending && (_jsx(Card, { className: "border-2 border-primary", children: _jsxs(CardContent, { className: "flex flex-wrap items-center justify-between gap-4 p-5", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("confirmPrintTitle") }), _jsx("p", { className: "text-2xl font-bold text-foreground", children: pending.document_number ?? t("document") }), _jsx("p", { className: "text-sm text-muted-foreground", children: [pending.order_number, pending.customer_name].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", size: "lg", onClick: cancelPending, disabled: busyId !== null, children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 px-8 text-lg", onClick: confirmPending, disabled: busyId !== null, children: [busyId === "confirm" ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("print")] })] })] }) })), _jsx(Card, { children: _jsx(CardContent, { className: "flex flex-wrap items-center gap-3 p-4", children: _jsxs("div", { className: "relative min-w-64 flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-9", placeholder: t("search"), value: filters.search, onChange: (e) => setFilters((f) => ({ ...f, search: e.target.value, page: 0 })) })] }) }) }), loading ? (_jsxs("div", { className: "flex items-center justify-center py-16 text-muted-foreground", children: [_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" }), " ", t("loadingQueue")] })) : (_jsx(QueueTable, { items: items, lockedIds: lockedIds, statuses: Array.isArray(statuses) ? statuses : [], documentTypes: Array.isArray(documentTypes) ? documentTypes : [], busyId: busyId, onPick: handlePick, onReprint: handleReprint, t: t })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-sm text-muted-foreground", children: [t("page"), " ", filters.page + 1, " ", t("of"), " ", totalPages] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", disabled: filters.page === 0, onClick: () => setFilters((f) => ({ ...f, page: Math.max(0, f.page - 1) })), children: t("previous") }), _jsx(Button, { variant: "outline", disabled: filters.page + 1 >= totalPages, onClick: () => setFilters((f) => ({ ...f, page: f.page + 1 })), children: t("next") })] })] })] }));
|
|
114
198
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PickDocumentType, PickQueueItem, PickStatus } from "../../lib/pickTypes";
|
|
2
|
+
import { type PickTranslator } from "../../lib/pickI18n";
|
|
2
3
|
interface Props {
|
|
3
4
|
items: PickQueueItem[];
|
|
4
5
|
lockedIds: Set<string>;
|
|
@@ -6,8 +7,10 @@ interface Props {
|
|
|
6
7
|
documentTypes: PickDocumentType[];
|
|
7
8
|
busyId: string | null;
|
|
8
9
|
onPick: (item: PickQueueItem) => void;
|
|
10
|
+
onReprint?: (item: PickQueueItem) => void;
|
|
9
11
|
readOnly?: boolean;
|
|
12
|
+
t?: PickTranslator;
|
|
10
13
|
}
|
|
11
|
-
export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, readOnly, }: Props): import("react").JSX.Element;
|
|
14
|
+
export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, readOnly, t: translator, }: Props): import("react").JSX.Element;
|
|
12
15
|
export {};
|
|
13
16
|
//# sourceMappingURL=QueueTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEvF,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE5E,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,CAAC,EAAE,cAAc,CAAC;CACpB;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAa,EACb,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,EACR,CAAC,EAAE,UAAU,GACd,EAAE,KAAK,+BA8GP"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Badge, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
|
|
3
|
-
import { AlertTriangle, Lock, Printer } from "lucide-react";
|
|
3
|
+
import { AlertTriangle, Lock, Printer, RotateCcw } from "lucide-react";
|
|
4
4
|
import { sinceLabel } from "../../lib/pickTypes";
|
|
5
|
+
import { getPickTranslator } from "../../lib/pickI18n";
|
|
5
6
|
function priorityTone(priority, urgent) {
|
|
6
7
|
if (urgent)
|
|
7
8
|
return "bg-destructive text-destructive-foreground";
|
|
@@ -11,19 +12,19 @@ function priorityTone(priority, urgent) {
|
|
|
11
12
|
return "bg-secondary text-secondary-foreground";
|
|
12
13
|
return "bg-muted text-muted-foreground";
|
|
13
14
|
}
|
|
14
|
-
export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, readOnly, }) {
|
|
15
|
+
export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, readOnly, t: translator, }) {
|
|
16
|
+
const t = translator ?? getPickTranslator("nl");
|
|
15
17
|
const safeItems = Array.isArray(items) ? items : [];
|
|
16
|
-
const statusById = new Map((Array.isArray(statuses) ? statuses : []).map((s) => [s.id, s]));
|
|
17
18
|
const docById = new Map((Array.isArray(documentTypes) ? documentTypes : []).map((d) => [d.id, d]));
|
|
18
|
-
return (_jsx("div", { className: "overflow-x-auto rounded-lg border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "
|
|
19
|
-
const
|
|
20
|
-
const
|
|
19
|
+
return (_jsx("div", { className: "overflow-x-auto rounded-lg border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t("document") }), _jsx(TableHead, { children: t("order") }), _jsx(TableHead, { children: t("customer") }), _jsx(TableHead, { className: "hidden lg:table-cell", children: t("deliveryAddress") }), _jsx(TableHead, { className: "text-right", children: t("lines") }), _jsx(TableHead, { className: "text-right", children: t("carts") }), _jsx(TableHead, { children: t("status") }), _jsx(TableHead, { children: t("priority") }), _jsx(TableHead, { children: t("announced") }), _jsx(TableHead, { children: t("waiting") }), _jsx(TableHead, { className: "text-right", children: t("action") })] }) }), _jsxs(TableBody, { children: [safeItems.map((item) => {
|
|
20
|
+
const printed = !!item.printed_at;
|
|
21
|
+
const locked = !printed && lockedIds.has(item.id);
|
|
21
22
|
const doc = item.document_type_id ? docById.get(item.document_type_id) : undefined;
|
|
22
23
|
const warnings = Array.isArray(item.warnings) ? item.warnings : [];
|
|
23
|
-
return (_jsxs(TableRow, { className: locked ? "opacity-
|
|
24
|
-
priorityTone(item.priority, item.is_urgent), children: item.is_urgent ? "
|
|
24
|
+
return (_jsxs(TableRow, { className: locked || printed ? "opacity-60" : undefined, children: [_jsxs(TableCell, { className: "font-medium", children: [_jsxs("div", { className: "flex items-center gap-2", children: [item.document_number, warnings.length > 0 && (_jsx(AlertTriangle, { className: "h-4 w-4 text-destructive", "aria-label": t("warning") }))] }), _jsx("div", { className: "text-xs text-muted-foreground", children: doc?.name ?? "-" })] }), _jsx(TableCell, { children: item.order_number }), _jsx(TableCell, { children: item.customer_name }), _jsx(TableCell, { className: "hidden max-w-56 truncate lg:table-cell", children: item.delivery_address }), _jsx(TableCell, { className: "text-right", children: item.line_count }), _jsx(TableCell, { className: "text-right", children: item.cart_count }), _jsx(TableCell, { children: _jsx(Badge, { variant: printed ? "secondary" : "default", children: printed ? t("statusPrinted") : t("statusToPrint") }) }), _jsx(TableCell, { children: _jsx("span", { className: "rounded px-2 py-1 text-xs font-semibold " +
|
|
25
|
+
priorityTone(item.priority, item.is_urgent), children: item.is_urgent ? t("urgent") : item.priority }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: new Date(item.announced_at).toLocaleTimeString(t.locale, {
|
|
25
26
|
hour: "2-digit",
|
|
26
27
|
minute: "2-digit",
|
|
27
|
-
}) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: sinceLabel(item.announced_at) }), _jsx(TableCell, { className: "text-right", children: locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), "
|
|
28
|
-
}), safeItems.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 11, className: "py-10 text-center text-muted-foreground", children: "
|
|
28
|
+
}) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: sinceLabel(item.announced_at) }), _jsx(TableCell, { className: "text-right", children: printed ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: readOnly || busyId === item.id, onClick: () => (onReprint ?? onPick)(item), children: [_jsx(RotateCcw, { className: "mr-1 h-4 w-4" }), t("print")] })) : locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), " ", t("inProgress")] })) : (_jsxs(Button, { size: "sm", variant: "outline", disabled: readOnly || busyId === item.id, onClick: () => onPick(item), children: [_jsx(Printer, { className: "mr-1 h-4 w-4" }), t("print")] })) })] }, item.id));
|
|
29
|
+
}), safeItems.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 11, className: "py-10 text-center text-muted-foreground", children: t("emptyQueue") }) }))] })] }) }));
|
|
29
30
|
}
|
|
@@ -21,6 +21,9 @@ export declare function usePickQueue(args: {
|
|
|
21
21
|
}): {
|
|
22
22
|
items: PickQueueItem[];
|
|
23
23
|
total: number;
|
|
24
|
+
pickDay: string | null;
|
|
25
|
+
pendingCount: number;
|
|
26
|
+
printedCount: number;
|
|
24
27
|
loading: boolean;
|
|
25
28
|
error: string | null;
|
|
26
29
|
lockedIds: Set<string>;
|
|
@@ -30,5 +33,8 @@ export declare function usePickQueue(args: {
|
|
|
30
33
|
export declare function usePickHeartbeat(stationId?: string, screenId?: string | null, sessionId?: string): {
|
|
31
34
|
online: boolean;
|
|
32
35
|
};
|
|
33
|
-
export declare function usePickCountryCounts(
|
|
36
|
+
export declare function usePickCountryCounts(args: {
|
|
37
|
+
stationId?: string;
|
|
38
|
+
screenId?: string;
|
|
39
|
+
}): import("@tanstack/react-query").UseQueryResult<NoInfer<Record<string, number>>, Error>;
|
|
34
40
|
//# sourceMappingURL=usePickQueue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAQ5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB
|
|
1
|
+
{"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAQ5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;;;;;;;;;;EA0GA;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM;;EAuBhG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,0FAOnF"}
|