sgerp-frontend-lib 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/index.d.ts +7 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +8 -0
  6. package/dist/locales/locale_en.d.ts +2 -0
  7. package/dist/locales/locale_en.d.ts.map +1 -0
  8. package/dist/locales/locale_en.js +1933 -0
  9. package/dist/locales/locale_ja.d.ts +2 -0
  10. package/dist/locales/locale_ja.d.ts.map +1 -0
  11. package/dist/locales/locale_ja.js +1926 -0
  12. package/dist/locales/locale_ms.d.ts +2 -0
  13. package/dist/locales/locale_ms.d.ts.map +1 -0
  14. package/dist/locales/locale_ms.js +1916 -0
  15. package/dist/sgerp/client.d.ts +236 -0
  16. package/dist/sgerp/client.d.ts.map +1 -0
  17. package/dist/sgerp/collections/simulation/node.d.ts +11 -0
  18. package/dist/sgerp/collections/simulation/node.d.ts.map +1 -0
  19. package/dist/sgerp/collections/simulation/vehicle.d.ts +11 -0
  20. package/dist/sgerp/collections/simulation/vehicle.d.ts.map +1 -0
  21. package/dist/sgerp/context/sgerp-context.d.ts +54 -0
  22. package/dist/sgerp/context/sgerp-context.d.ts.map +1 -0
  23. package/dist/sgerp/hooks/use-collection.d.ts +83 -0
  24. package/dist/sgerp/hooks/use-collection.d.ts.map +1 -0
  25. package/dist/sgerp/hooks/use-live-updates.d.ts +35 -0
  26. package/dist/sgerp/hooks/use-live-updates.d.ts.map +1 -0
  27. package/dist/sgerp/hooks/use-live-updates.js +95 -0
  28. package/dist/sgerp/index.d.ts +90 -0
  29. package/dist/sgerp/index.d.ts.map +1 -0
  30. package/dist/sgerp/simulation-logic/fetchUtils.d.ts +69 -0
  31. package/dist/sgerp/simulation-logic/fetchUtils.d.ts.map +1 -0
  32. package/dist/sgerp/simulation-logic/index.d.ts +14 -0
  33. package/dist/sgerp/simulation-logic/index.d.ts.map +1 -0
  34. package/dist/sgerp/simulation-logic/index.js +11 -0
  35. package/dist/sgerp/simulation-logic/manualEditUtils.d.ts +70 -0
  36. package/dist/sgerp/simulation-logic/manualEditUtils.d.ts.map +1 -0
  37. package/dist/sgerp/simulation-logic/mapUtils.d.ts +11 -0
  38. package/dist/sgerp/simulation-logic/mapUtils.d.ts.map +1 -0
  39. package/dist/sgerp/simulation-logic/optimisticUpdateUtils.d.ts +28 -0
  40. package/dist/sgerp/simulation-logic/optimisticUpdateUtils.d.ts.map +1 -0
  41. package/dist/sgerp/simulation-logic/optimisticUpdateUtils.js +37 -0
  42. package/dist/sgerp/simulation-logic/referenceUtils.d.ts +28 -0
  43. package/dist/sgerp/simulation-logic/referenceUtils.d.ts.map +1 -0
  44. package/dist/sgerp/simulation-logic/routeCalculationUtils.d.ts +12 -0
  45. package/dist/sgerp/simulation-logic/routeCalculationUtils.d.ts.map +1 -0
  46. package/dist/sgerp/simulation-logic/timeShiftUtils.d.ts +27 -0
  47. package/dist/sgerp/simulation-logic/timeShiftUtils.d.ts.map +1 -0
  48. package/dist/sgerp/types/simulation/node.d.ts +102 -0
  49. package/dist/sgerp/types/simulation/node.d.ts.map +1 -0
  50. package/dist/sgerp/types/simulation/node.js +11 -0
  51. package/dist/sgerp/types/simulation/vehicle.d.ts +88 -0
  52. package/dist/sgerp/types/simulation/vehicle.d.ts.map +1 -0
  53. package/dist/sgerp/types/simulation/vehicle.js +1 -0
  54. package/dist/sgerp/utils/routeUtils.d.ts +47 -0
  55. package/dist/sgerp/utils/routeUtils.d.ts.map +1 -0
  56. package/package.json +126 -0
@@ -0,0 +1,88 @@
1
+ import type { RoutingEngineSettings } from './routing-engine-settings';
2
+ /**
3
+ * Vehicle model from simulation app
4
+ */
5
+ export interface Vehicle {
6
+ id: number;
7
+ h3: string | null;
8
+ lat: number;
9
+ lon: number;
10
+ ts: string | null;
11
+ bearing: number;
12
+ created_at: string;
13
+ modified_at: string;
14
+ agent_id: string | null;
15
+ simulation_id: number;
16
+ current_sim_ts: string;
17
+ previous_sim_ts: string;
18
+ simulation_step_pause: number;
19
+ simulation_time_speedup_factor: number;
20
+ init_server_ts: string;
21
+ server_ts: string;
22
+ capacity: Record<string, number>;
23
+ routing_engine_settings: RoutingEngineSettings;
24
+ characteristics: Record<string, unknown>;
25
+ efficiency: number | null;
26
+ geofence_ids: number[];
27
+ labels: unknown | null;
28
+ vehicle_cost: number | null;
29
+ lifo_order_check: boolean;
30
+ max_physical_stops: number | null;
31
+ dynamic_break_duration: number | null;
32
+ dynamic_break_min_path_duration: number | null;
33
+ dynamic_break_avg_time_between_breaks: number | null;
34
+ dynamic_break_max_latency: number | null;
35
+ number_of_trips: number | null;
36
+ max_trip_length: number | null;
37
+ max_trip_duration: number | null;
38
+ max_pickup_locations: number | null;
39
+ max_dropoff_locations: number | null;
40
+ zero_cost_if_only_partial_routes: boolean | null;
41
+ assigned_nodes_protection_interval: number | null;
42
+ assigned_nodes_protection_max_locations: number | null;
43
+ vehicle_type_id: number | null;
44
+ registration_number: string | null;
45
+ speed: number;
46
+ current_route: {
47
+ points: Array<[number, number]>;
48
+ } | null;
49
+ traffic_sim_dependency_function: unknown | null;
50
+ last_assignment_ts: string | null;
51
+ should_reach_for: number | null;
52
+ should_reach_at: string | null;
53
+ status: string;
54
+ should_wait_until: string | null;
55
+ start_time: string | null;
56
+ end_time: string | null;
57
+ assignment_id: number | null;
58
+ path: unknown | null;
59
+ physical_vehicle_id: number | null;
60
+ in_use: string;
61
+ service_number: string | null;
62
+ sim_enable_gps_noise: boolean;
63
+ sim_gps_noise_distance: number;
64
+ driver_id: number | null;
65
+ amortized_linear_cost_factor: number | null;
66
+ amortized_quadratic_cost_factor: number | null;
67
+ color: string | null;
68
+ start_time_node_index: number | null;
69
+ end_time_node_index: number | null;
70
+ dynamic_break_start_time: string | null;
71
+ dynamic_break_end_time: string | null;
72
+ export_system_name: string | null;
73
+ export_last_attempt_status: string | null;
74
+ export_last_attempt_ts: string | null;
75
+ export_in_progress: boolean | null;
76
+ export_progress_started_at: string | null;
77
+ export_last_attempt_initiator_username: string | null;
78
+ export_last_attempt_initiator_user_id: number | null;
79
+ project_id: number;
80
+ gps_modified_at: string | null;
81
+ is_invalidated: boolean;
82
+ driver_login_session_modified_at: string | null;
83
+ planned_total_distance: number | null;
84
+ planned_total_travel_time: number | null;
85
+ planned_route_polyline: string | null;
86
+ planned_parameters_modified_at: string | null;
87
+ }
88
+ //# sourceMappingURL=vehicle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vehicle.d.ts","sourceRoot":"","sources":["../../../../sgerplib/sgerp/types/simulation/vehicle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Route utility functions adapted from dashviewer
3
+ * Generates waypoint routes from nodes without web workers
4
+ */
5
+ import type { Node } from '@/sgerplib/sgerp/types/simulation/node';
6
+ export type RouteNode = Node;
7
+ export interface Waypoint {
8
+ id: string;
9
+ idx: number;
10
+ lat: number;
11
+ lon: number;
12
+ location_name: string;
13
+ nodes: RouteNode[];
14
+ pickup_nodes: RouteNode[];
15
+ dropoff_nodes: RouteNode[];
16
+ point_nodes: RouteNode[];
17
+ transit_nodes: RouteNode[];
18
+ scheduled_ts?: string | null;
19
+ sequence: number;
20
+ }
21
+ export interface VehicleRouteData {
22
+ vehicleId: number;
23
+ waypoints: Waypoint[];
24
+ googleMapsLink: string;
25
+ }
26
+ /**
27
+ * Generate waypoint route from nodes
28
+ * Groups consecutive nodes at the same location into waypoints
29
+ */
30
+ export declare function generateWaypointRouteFromNodes(nodes: RouteNode[]): {
31
+ route: Waypoint[];
32
+ googleMapsLink: string;
33
+ };
34
+ /**
35
+ * Validate pickup-dropoff constraint
36
+ * Returns error messages if any dropoff happens before its corresponding pickup
37
+ *
38
+ * @param waypoints - Array of waypoints with nodes
39
+ * @returns Array of error messages (empty if valid)
40
+ */
41
+ export declare function validatePickupDropoffConstraint(waypoints: Waypoint[]): string[];
42
+ /**
43
+ * Create vehicle route data from nodes
44
+ * Groups nodes by vehicle and generates waypoint routes
45
+ */
46
+ export declare function createVehicleRoutesFromNodes(nodes: RouteNode[], vehicleIds: number[]): Map<number, VehicleRouteData>;
47
+ //# sourceMappingURL=routeUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeUtils.d.ts","sourceRoot":"","sources":["../../../sgerplib/sgerp/utils/routeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wCAAwC,CAAA;AAElE,MAAM,MAAM,SAAS,GAAG,IAAI,CAAA;AAE5B,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG;IAClE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB,CA6FA;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CA4B/E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,SAAS,EAAE,EAClB,UAAU,EAAE,MAAM,EAAE,GACnB,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAwC/B"}
package/package.json ADDED
@@ -0,0 +1,126 @@
1
+ {
2
+ "name": "sgerp-frontend-lib",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript/React library for interacting with the SGERP API, providing client SDK, Backbone.js-style Collections, and pre-built React components",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "keywords": [
14
+ "sgerp",
15
+ "typescript",
16
+ "react",
17
+ "api-client",
18
+ "collections",
19
+ "transportation",
20
+ "logistics",
21
+ "routing",
22
+ "simulation"
23
+ ],
24
+ "license": "MIT",
25
+ "author": "SGERP Team",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "scripts": {
30
+ "dev": "next dev --turbopack",
31
+ "build": "next build --turbopack",
32
+ "build:lib": "tsc -p tsconfig.lib.json",
33
+ "build:lib:watch": "tsc -p tsconfig.lib.json --watch",
34
+ "prepublishOnly": "npm run build:lib",
35
+ "start": "next start",
36
+ "lint": "eslint --max-warnings 0",
37
+ "lint:check": "eslint --max-warnings 0",
38
+ "test": "vitest",
39
+ "test:ui": "vitest --ui",
40
+ "test:run": "vitest run",
41
+ "test:coverage": "vitest run --coverage",
42
+ "test:e2e": "playwright test",
43
+ "test:e2e:ui": "playwright test --ui",
44
+ "test:e2e:ptapp": "playwright test e2e/ptapp/",
45
+ "test:e2e:passengers": "playwright test e2e/ptapp/passengers.spec.ts",
46
+ "test:e2e:drivers": "playwright test e2e/ptapp/drivers.spec.ts",
47
+ "test:e2e:notifications": "playwright test e2e/ptapp/notifications.spec.ts",
48
+ "test:e2e:geofences": "playwright test e2e/ptapp/geofences.spec.ts",
49
+ "test:e2e:services": "playwright test e2e/ptapp/services.spec.ts",
50
+ "test:e2e:templates": "playwright test e2e/ptapp/templates.spec.ts",
51
+ "test:e2e:pricings": "playwright test e2e/ptapp/pricings.spec.ts",
52
+ "test:e2e:transitstopsets": "playwright test e2e/ptapp/transitstopsets.spec.ts",
53
+ "test:all": "./run-tests.sh",
54
+ "test:all:open": "./run-tests.sh --open-coverage",
55
+ "prepare": "husky"
56
+ },
57
+ "dependencies": {
58
+ "@hello-pangea/dnd": "^18.0.1",
59
+ "@mapbox/mapbox-gl-draw": "^1.5.0",
60
+ "@mapbox/polyline": "^1.2.1",
61
+ "@radix-ui/react-accordion": "^1.2.12",
62
+ "@radix-ui/react-checkbox": "^1.3.3",
63
+ "@radix-ui/react-collapsible": "^1.1.12",
64
+ "@radix-ui/react-dialog": "^1.1.15",
65
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
66
+ "@radix-ui/react-label": "^2.1.7",
67
+ "@radix-ui/react-navigation-menu": "^1.2.14",
68
+ "@radix-ui/react-popover": "^1.1.15",
69
+ "@radix-ui/react-progress": "^1.1.7",
70
+ "@radix-ui/react-radio-group": "^1.3.8",
71
+ "@radix-ui/react-scroll-area": "^1.2.10",
72
+ "@radix-ui/react-select": "^2.2.6",
73
+ "@radix-ui/react-separator": "^1.1.7",
74
+ "@radix-ui/react-slider": "^1.3.6",
75
+ "@radix-ui/react-slot": "^1.2.3",
76
+ "@radix-ui/react-tabs": "^1.1.13",
77
+ "@radix-ui/react-toggle": "^1.1.10",
78
+ "@radix-ui/react-toggle-group": "^1.1.11",
79
+ "@radix-ui/react-tooltip": "^1.2.8",
80
+ "class-variance-authority": "^0.7.1",
81
+ "clsx": "^2.1.1",
82
+ "cmdk": "^1.1.1",
83
+ "date-fns": "^3.6.0",
84
+ "date-fns-tz": "^3.2.0",
85
+ "gray-matter": "^4.0.3",
86
+ "lucide-react": "^0.545.0",
87
+ "mapbox-gl": "^3.16.0",
88
+ "moment-timezone": "^0.6.0",
89
+ "next": "15.5.4",
90
+ "next-themes": "^0.4.6",
91
+ "nuqs": "^2.7.2",
92
+ "react": "^19.1.0",
93
+ "react-day-picker": "^9.11.1",
94
+ "react-dom": "19.1.0",
95
+ "react-markdown": "^10.1.0",
96
+ "rehype-highlight": "^7.0.2",
97
+ "rehype-slug": "^6.0.0",
98
+ "remark-gfm": "^4.0.1",
99
+ "sonner": "^2.0.7",
100
+ "tailwind-merge": "^3.3.1",
101
+ "underscore": "^1.13.7"
102
+ },
103
+ "devDependencies": {
104
+ "@eslint/eslintrc": "^3",
105
+ "@playwright/test": "^1.56.1",
106
+ "@tailwindcss/postcss": "^4",
107
+ "@testing-library/react": "^16.3.0",
108
+ "@testing-library/user-event": "^14.6.1",
109
+ "@types/node": "^20",
110
+ "@types/react": "^19",
111
+ "@types/react-dom": "^19",
112
+ "@types/underscore": "^1.13.0",
113
+ "@vitejs/plugin-react": "^5.0.4",
114
+ "@vitest/coverage-v8": "^3.2.4",
115
+ "babel-plugin-react-compiler": "^1.0.0",
116
+ "dotenv": "^17.2.3",
117
+ "eslint": "^9",
118
+ "eslint-config-next": "15.5.4",
119
+ "husky": "^9.1.7",
120
+ "jsdom": "^27.0.1",
121
+ "tailwindcss": "^4",
122
+ "tw-animate-css": "^1.4.0",
123
+ "typescript": "^5",
124
+ "vitest": "^3.2.4"
125
+ }
126
+ }