@freighttech/shipment-tracking 0.6.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/LICENSE +21 -0
- package/NOTICE +25 -0
- package/dist/generated/entities/bic_config/index.js +21 -0
- package/dist/generated/entities/bic_config/index.js.map +7 -0
- package/dist/generated/entities/carrier_config/index.js +27 -0
- package/dist/generated/entities/carrier_config/index.js.map +7 -0
- package/dist/generated/entities/location_override/index.js +33 -0
- package/dist/generated/entities/location_override/index.js.map +7 -0
- package/dist/generated/entities/shipment/index.js +73 -0
- package/dist/generated/entities/shipment/index.js.map +7 -0
- package/dist/generated/entities/ships_go_config/index.js +31 -0
- package/dist/generated/entities/ships_go_config/index.js.map +7 -0
- package/dist/generated/entities/tracking_event/index.js +101 -0
- package/dist/generated/entities/tracking_event/index.js.map +7 -0
- package/dist/generated/entities/tracking_job/index.js +47 -0
- package/dist/generated/entities/tracking_job/index.js.map +7 -0
- package/dist/generated/entities/webhook/index.js +25 -0
- package/dist/generated/entities/webhook/index.js.map +7 -0
- package/dist/generated/entities/webhook_delivery/index.js +25 -0
- package/dist/generated/entities/webhook_delivery/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +21 -0
- package/dist/generated/entities.ids.generated.js.map +7 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +7 -0
- package/dist/modules/shipment_tracking/acl.js +22 -0
- package/dist/modules/shipment_tracking/acl.js.map +7 -0
- package/dist/modules/shipment_tracking/api/bic-configs/route.js +176 -0
- package/dist/modules/shipment_tracking/api/bic-configs/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/bic-configs/test/route.js +95 -0
- package/dist/modules/shipment_tracking/api/bic-configs/test/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/cargo-events/route.js +93 -0
- package/dist/modules/shipment_tracking/api/cargo-events/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/carrier-configs/route.js +139 -0
- package/dist/modules/shipment_tracking/api/carrier-configs/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/dashboard/ships-map/route.js +177 -0
- package/dist/modules/shipment_tracking/api/dashboard/ships-map/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/location-overrides/route.js +179 -0
- package/dist/modules/shipment_tracking/api/location-overrides/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/openapi.js +27 -0
- package/dist/modules/shipment_tracking/api/openapi.js.map +7 -0
- package/dist/modules/shipment_tracking/api/shipments/route.js +192 -0
- package/dist/modules/shipment_tracking/api/shipments/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/shipsgo-configs/route.js +185 -0
- package/dist/modules/shipment_tracking/api/shipsgo-configs/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/tracking-jobs/route.js +144 -0
- package/dist/modules/shipment_tracking/api/tracking-jobs/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/tracking-jobs/sync/route.js +107 -0
- package/dist/modules/shipment_tracking/api/tracking-jobs/sync/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/utils.js +12 -0
- package/dist/modules/shipment_tracking/api/utils.js.map +7 -0
- package/dist/modules/shipment_tracking/api/webhooks/deliveries/route.js +76 -0
- package/dist/modules/shipment_tracking/api/webhooks/deliveries/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/webhooks/route.js +135 -0
- package/dist/modules/shipment_tracking/api/webhooks/route.js.map +7 -0
- package/dist/modules/shipment_tracking/api/webhooks/test/route.js +71 -0
- package/dist/modules/shipment_tracking/api/webhooks/test/route.js.map +7 -0
- package/dist/modules/shipment_tracking/assets/carriers/cma_cgm.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/cosco.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/evergreen.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/hapag_lloyd.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/maersk.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/msc.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/one.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/oocl.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/yang_ming.png +0 -0
- package/dist/modules/shipment_tracking/assets/carriers/zim.png +0 -0
- package/dist/modules/shipment_tracking/assets/index.js +52 -0
- package/dist/modules/shipment_tracking/assets/index.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/carrier-configs/page.js +621 -0
- package/dist/modules/shipment_tracking/backend/carrier-configs/page.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/carrier-configs/page.meta.js +19 -0
- package/dist/modules/shipment_tracking/backend/carrier-configs/page.meta.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/location-overrides/page.js +198 -0
- package/dist/modules/shipment_tracking/backend/location-overrides/page.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/location-overrides/page.meta.js +19 -0
- package/dist/modules/shipment_tracking/backend/location-overrides/page.meta.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/shipment-tracking/page.js +279 -0
- package/dist/modules/shipment_tracking/backend/shipment-tracking/page.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/shipment-tracking/page.meta.js +19 -0
- package/dist/modules/shipment_tracking/backend/shipment-tracking/page.meta.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/tracking-jobs/page.js +10 -0
- package/dist/modules/shipment_tracking/backend/tracking-jobs/page.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/tracking-jobs/page.meta.js +19 -0
- package/dist/modules/shipment_tracking/backend/tracking-jobs/page.meta.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/webhooks/page.js +198 -0
- package/dist/modules/shipment_tracking/backend/webhooks/page.js.map +7 -0
- package/dist/modules/shipment_tracking/backend/webhooks/page.meta.js +19 -0
- package/dist/modules/shipment_tracking/backend/webhooks/page.meta.js.map +7 -0
- package/dist/modules/shipment_tracking/ce.js +52 -0
- package/dist/modules/shipment_tracking/ce.js.map +7 -0
- package/dist/modules/shipment_tracking/cli.js +229 -0
- package/dist/modules/shipment_tracking/cli.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/bic-configs.js +66 -0
- package/dist/modules/shipment_tracking/commands/bic-configs.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/carrier-configs.js +65 -0
- package/dist/modules/shipment_tracking/commands/carrier-configs.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/index.js +9 -0
- package/dist/modules/shipment_tracking/commands/index.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/location-overrides.js +93 -0
- package/dist/modules/shipment_tracking/commands/location-overrides.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/shipments.js +200 -0
- package/dist/modules/shipment_tracking/commands/shipments.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/shipsgo-configs.js +75 -0
- package/dist/modules/shipment_tracking/commands/shipsgo-configs.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/tracking-jobs.js +120 -0
- package/dist/modules/shipment_tracking/commands/tracking-jobs.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/tracking.js +140 -0
- package/dist/modules/shipment_tracking/commands/tracking.js.map +7 -0
- package/dist/modules/shipment_tracking/commands/webhooks.js +115 -0
- package/dist/modules/shipment_tracking/commands/webhooks.js.map +7 -0
- package/dist/modules/shipment_tracking/components/CombinedTimestampCell.js +168 -0
- package/dist/modules/shipment_tracking/components/CombinedTimestampCell.js.map +7 -0
- package/dist/modules/shipment_tracking/components/FacilityLocationInput.js +202 -0
- package/dist/modules/shipment_tracking/components/FacilityLocationInput.js.map +7 -0
- package/dist/modules/shipment_tracking/components/LocationOverrideDrawer.js +501 -0
- package/dist/modules/shipment_tracking/components/LocationOverrideDrawer.js.map +7 -0
- package/dist/modules/shipment_tracking/components/ShipmentDetailsDrawer.js +818 -0
- package/dist/modules/shipment_tracking/components/ShipmentDetailsDrawer.js.map +7 -0
- package/dist/modules/shipment_tracking/components/ShipmentDrawer.js +404 -0
- package/dist/modules/shipment_tracking/components/ShipmentDrawer.js.map +7 -0
- package/dist/modules/shipment_tracking/components/ShipsGoConfigSection.js +200 -0
- package/dist/modules/shipment_tracking/components/ShipsGoConfigSection.js.map +7 -0
- package/dist/modules/shipment_tracking/components/TimestampCell.js +108 -0
- package/dist/modules/shipment_tracking/components/TimestampCell.js.map +7 -0
- package/dist/modules/shipment_tracking/components/TrackingJobDrawer.js +343 -0
- package/dist/modules/shipment_tracking/components/TrackingJobDrawer.js.map +7 -0
- package/dist/modules/shipment_tracking/components/VesselTrackingMap.js +496 -0
- package/dist/modules/shipment_tracking/components/VesselTrackingMap.js.map +7 -0
- package/dist/modules/shipment_tracking/components/WebhookDrawer.js +332 -0
- package/dist/modules/shipment_tracking/components/WebhookDrawer.js.map +7 -0
- package/dist/modules/shipment_tracking/data/entities.js +686 -0
- package/dist/modules/shipment_tracking/data/entities.js.map +7 -0
- package/dist/modules/shipment_tracking/data/validators.js +434 -0
- package/dist/modules/shipment_tracking/data/validators.js.map +7 -0
- package/dist/modules/shipment_tracking/di.js +60 -0
- package/dist/modules/shipment_tracking/di.js.map +7 -0
- package/dist/modules/shipment_tracking/encryption.js +12 -0
- package/dist/modules/shipment_tracking/encryption.js.map +7 -0
- package/dist/modules/shipment_tracking/events.js +87 -0
- package/dist/modules/shipment_tracking/events.js.map +7 -0
- package/dist/modules/shipment_tracking/hooks/useVesselTracking.js +137 -0
- package/dist/modules/shipment_tracking/hooks/useVesselTracking.js.map +7 -0
- package/dist/modules/shipment_tracking/i18n/de.json +327 -0
- package/dist/modules/shipment_tracking/i18n/en.json +327 -0
- package/dist/modules/shipment_tracking/i18n/es.json +327 -0
- package/dist/modules/shipment_tracking/i18n/pl.json +327 -0
- package/dist/modules/shipment_tracking/index.js +15 -0
- package/dist/modules/shipment_tracking/index.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/cma-cgm.js +66 -0
- package/dist/modules/shipment_tracking/lib/adapters/cma-cgm.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/cosco-types.js +1 -0
- package/dist/modules/shipment_tracking/lib/adapters/cosco-types.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/cosco.js +236 -0
- package/dist/modules/shipment_tracking/lib/adapters/cosco.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/evergreen.js +87 -0
- package/dist/modules/shipment_tracking/lib/adapters/evergreen.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/hapag-lloyd.js +68 -0
- package/dist/modules/shipment_tracking/lib/adapters/hapag-lloyd.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/index.js +20 -0
- package/dist/modules/shipment_tracking/lib/adapters/index.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/maersk.js +84 -0
- package/dist/modules/shipment_tracking/lib/adapters/maersk.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/msc.js +170 -0
- package/dist/modules/shipment_tracking/lib/adapters/msc.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/adapters/zim.js +85 -0
- package/dist/modules/shipment_tracking/lib/adapters/zim.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/audit-helpers.js +20 -0
- package/dist/modules/shipment_tracking/lib/audit-helpers.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/auth/base64url.js +8 -0
- package/dist/modules/shipment_tracking/lib/auth/base64url.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/auth/oauth-client.js +38 -0
- package/dist/modules/shipment_tracking/lib/auth/oauth-client.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/background.js +15 -0
- package/dist/modules/shipment_tracking/lib/background.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/bic-api-client.js +106 -0
- package/dist/modules/shipment_tracking/lib/bic-api-client.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/carrier-adapter.js +17 -0
- package/dist/modules/shipment_tracking/lib/carrier-adapter.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/current-vessel.js +149 -0
- package/dist/modules/shipment_tracking/lib/current-vessel.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/dcsa-event-mapping.js +124 -0
- package/dist/modules/shipment_tracking/lib/dcsa-event-mapping.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/dcsa-event-parser.js +112 -0
- package/dist/modules/shipment_tracking/lib/dcsa-event-parser.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/dcsa-params.js +16 -0
- package/dist/modules/shipment_tracking/lib/dcsa-params.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/empty-return.js +48 -0
- package/dist/modules/shipment_tracking/lib/empty-return.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/location-overrides.js +85 -0
- package/dist/modules/shipment_tracking/lib/location-overrides.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/location-types.js +59 -0
- package/dist/modules/shipment_tracking/lib/location-types.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/logger.js +113 -0
- package/dist/modules/shipment_tracking/lib/logger.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/poi-event-processor.js +183 -0
- package/dist/modules/shipment_tracking/lib/poi-event-processor.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/poi-nats-config.js +52 -0
- package/dist/modules/shipment_tracking/lib/poi-nats-config.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/poi-types.js +43 -0
- package/dist/modules/shipment_tracking/lib/poi-types.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/rate-limiter.js +31 -0
- package/dist/modules/shipment_tracking/lib/rate-limiter.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/route-extraction.js +187 -0
- package/dist/modules/shipment_tracking/lib/route-extraction.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/route-inference.js +106 -0
- package/dist/modules/shipment_tracking/lib/route-inference.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/schedule-generator.js +63 -0
- package/dist/modules/shipment_tracking/lib/schedule-generator.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/shipsgo-client.js +143 -0
- package/dist/modules/shipment_tracking/lib/shipsgo-client.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/shipsgo-mapper.js +204 -0
- package/dist/modules/shipment_tracking/lib/shipsgo-mapper.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/status-machine.js +131 -0
- package/dist/modules/shipment_tracking/lib/status-machine.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/time-extraction.js +41 -0
- package/dist/modules/shipment_tracking/lib/time-extraction.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/timestamp-utils.js +100 -0
- package/dist/modules/shipment_tracking/lib/timestamp-utils.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/vessel-api.js +111 -0
- package/dist/modules/shipment_tracking/lib/vessel-api.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/vessel-cache.js +50 -0
- package/dist/modules/shipment_tracking/lib/vessel-cache.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/vessel-extraction.js +13 -0
- package/dist/modules/shipment_tracking/lib/vessel-extraction.js.map +7 -0
- package/dist/modules/shipment_tracking/lib/webhook-dispatcher.js +62 -0
- package/dist/modules/shipment_tracking/lib/webhook-dispatcher.js.map +7 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.js +48 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.js.map +7 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.js +15 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.js.map +7 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.js +47 -0
- package/dist/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.js.map +7 -0
- package/dist/modules/shipment_tracking/notifications.js +145 -0
- package/dist/modules/shipment_tracking/notifications.js.map +7 -0
- package/dist/modules/shipment_tracking/services/carrierRegistry.js +24 -0
- package/dist/modules/shipment_tracking/services/carrierRegistry.js.map +7 -0
- package/dist/modules/shipment_tracking/services/poiNatsService.js +397 -0
- package/dist/modules/shipment_tracking/services/poiNatsService.js.map +7 -0
- package/dist/modules/shipment_tracking/services/shipsGoProvider.js +163 -0
- package/dist/modules/shipment_tracking/services/shipsGoProvider.js.map +7 -0
- package/dist/modules/shipment_tracking/services/trackingService.js +1283 -0
- package/dist/modules/shipment_tracking/services/trackingService.js.map +7 -0
- package/dist/modules/shipment_tracking/services/webhookService.js +263 -0
- package/dist/modules/shipment_tracking/services/webhookService.js.map +7 -0
- package/dist/modules/shipment_tracking/setup.js +72 -0
- package/dist/modules/shipment_tracking/setup.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/cargo-event-created.js +60 -0
- package/dist/modules/shipment_tracking/subscribers/cargo-event-created.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.js +58 -0
- package/dist/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/poi-event-notification.js +82 -0
- package/dist/modules/shipment_tracking/subscribers/poi-event-notification.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.js +53 -0
- package/dist/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/shipment-status-changed.js +28 -0
- package/dist/modules/shipment_tracking/subscribers/shipment-status-changed.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/terminal-event-ingest.js +67 -0
- package/dist/modules/shipment_tracking/subscribers/terminal-event-ingest.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/tracking-job-initial-poll.js +30 -0
- package/dist/modules/shipment_tracking/subscribers/tracking-job-initial-poll.js.map +7 -0
- package/dist/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.js +19 -0
- package/dist/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.js.map +7 -0
- package/dist/modules/shipment_tracking/tables/index.js +6 -0
- package/dist/modules/shipment_tracking/tables/index.js.map +7 -0
- package/dist/modules/shipment_tracking/tables/tracking_job/table.client.js +284 -0
- package/dist/modules/shipment_tracking/tables/tracking_job/table.client.js.map +7 -0
- package/dist/modules/shipment_tracking/tables/tracking_job/table.js +36 -0
- package/dist/modules/shipment_tracking/tables/tracking_job/table.js.map +7 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/config.js +25 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/config.js.map +7 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.js +355 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.js.map +7 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.js +26 -0
- package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.js.map +7 -0
- package/dist/types/assets.d.js +1 -0
- package/dist/types/assets.d.js.map +7 -0
- package/generated/entities/bic_config/index.ts +20 -0
- package/generated/entities/carrier_config/index.ts +23 -0
- package/generated/entities/location_override/index.ts +26 -0
- package/generated/entities/shipment/index.ts +46 -0
- package/generated/entities/ships_go_config/index.ts +25 -0
- package/generated/entities/tracking_event/index.ts +60 -0
- package/generated/entities/tracking_job/index.ts +33 -0
- package/generated/entities/webhook/index.ts +22 -0
- package/generated/entities/webhook_delivery/index.ts +22 -0
- package/generated/entities.ids.generated.ts +47 -0
- package/package.json +81 -0
- package/src/index.ts +39 -0
- package/src/modules/shipment_tracking/__integration__/TC-TRACK-410-shipsgo-config-api.spec.ts +133 -0
- package/src/modules/shipment_tracking/__integration__/meta.ts +4 -0
- package/src/modules/shipment_tracking/__tests__/empty-return-stop.test.ts +231 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/hapag-lloyd-transship-container.json +702 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/index.ts +434 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/maersk-multi-transship-completed.json +1518 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/maersk-transship-intransit.json +558 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/msc-direct.json +222 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/msc-multi-transship-completed.json +974 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/msc-multi.json +4846 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/msc-transship.json +409 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/poi-events.json +240 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/synthetic/index.ts +138 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-eta-updates.json +288 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-route-inference.json +201 -0
- package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-voyage-progression.json +410 -0
- package/src/modules/shipment_tracking/__tests__/shipsgo-air-mapper.test.ts +157 -0
- package/src/modules/shipment_tracking/__tests__/shipsgo-client.test.ts +155 -0
- package/src/modules/shipment_tracking/__tests__/shipsgo-mapper.test.ts +201 -0
- package/src/modules/shipment_tracking/__tests__/shipsgo-poll.test.ts +357 -0
- package/src/modules/shipment_tracking/__tests__/shipsgo-provider.test.ts +364 -0
- package/src/modules/shipment_tracking/__tests__/trackingService.integration.test.ts +2248 -0
- package/src/modules/shipment_tracking/__tests__/webhookPayload.test.ts +151 -0
- package/src/modules/shipment_tracking/acl.ts +18 -0
- package/src/modules/shipment_tracking/api/bic-configs/route.ts +206 -0
- package/src/modules/shipment_tracking/api/bic-configs/test/route.ts +108 -0
- package/src/modules/shipment_tracking/api/cargo-events/route.ts +101 -0
- package/src/modules/shipment_tracking/api/carrier-configs/route.ts +142 -0
- package/src/modules/shipment_tracking/api/dashboard/ships-map/route.ts +246 -0
- package/src/modules/shipment_tracking/api/location-overrides/route.ts +185 -0
- package/src/modules/shipment_tracking/api/openapi.ts +28 -0
- package/src/modules/shipment_tracking/api/shipments/route.ts +197 -0
- package/src/modules/shipment_tracking/api/shipsgo-configs/route.ts +215 -0
- package/src/modules/shipment_tracking/api/tracking-jobs/route.ts +149 -0
- package/src/modules/shipment_tracking/api/tracking-jobs/sync/route.ts +116 -0
- package/src/modules/shipment_tracking/api/utils.ts +10 -0
- package/src/modules/shipment_tracking/api/webhooks/deliveries/route.ts +82 -0
- package/src/modules/shipment_tracking/api/webhooks/route.ts +138 -0
- package/src/modules/shipment_tracking/api/webhooks/test/route.ts +84 -0
- package/src/modules/shipment_tracking/assets/carriers/cma_cgm.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/cosco.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/evergreen.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/hapag_lloyd.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/maersk.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/msc.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/one.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/oocl.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/yang_ming.png +0 -0
- package/src/modules/shipment_tracking/assets/carriers/zim.png +0 -0
- package/src/modules/shipment_tracking/assets/index.ts +66 -0
- package/src/modules/shipment_tracking/backend/carrier-configs/page.meta.ts +16 -0
- package/src/modules/shipment_tracking/backend/carrier-configs/page.tsx +782 -0
- package/src/modules/shipment_tracking/backend/location-overrides/page.meta.ts +16 -0
- package/src/modules/shipment_tracking/backend/location-overrides/page.tsx +241 -0
- package/src/modules/shipment_tracking/backend/shipment-tracking/page.meta.ts +16 -0
- package/src/modules/shipment_tracking/backend/shipment-tracking/page.tsx +340 -0
- package/src/modules/shipment_tracking/backend/tracking-jobs/page.meta.ts +16 -0
- package/src/modules/shipment_tracking/backend/tracking-jobs/page.tsx +16 -0
- package/src/modules/shipment_tracking/backend/webhooks/page.meta.ts +16 -0
- package/src/modules/shipment_tracking/backend/webhooks/page.tsx +228 -0
- package/src/modules/shipment_tracking/ce.ts +48 -0
- package/src/modules/shipment_tracking/cli.ts +321 -0
- package/src/modules/shipment_tracking/commands/bic-configs.ts +94 -0
- package/src/modules/shipment_tracking/commands/carrier-configs.ts +89 -0
- package/src/modules/shipment_tracking/commands/index.ts +8 -0
- package/src/modules/shipment_tracking/commands/location-overrides.ts +119 -0
- package/src/modules/shipment_tracking/commands/shipments.ts +247 -0
- package/src/modules/shipment_tracking/commands/shipsgo-configs.ts +101 -0
- package/src/modules/shipment_tracking/commands/tracking-jobs.ts +158 -0
- package/src/modules/shipment_tracking/commands/tracking.ts +230 -0
- package/src/modules/shipment_tracking/commands/webhooks.ts +159 -0
- package/src/modules/shipment_tracking/components/CombinedTimestampCell.tsx +236 -0
- package/src/modules/shipment_tracking/components/FacilityLocationInput.tsx +235 -0
- package/src/modules/shipment_tracking/components/LocationOverrideDrawer.tsx +586 -0
- package/src/modules/shipment_tracking/components/ShipmentDetailsDrawer.tsx +1364 -0
- package/src/modules/shipment_tracking/components/ShipmentDrawer.tsx +498 -0
- package/src/modules/shipment_tracking/components/ShipsGoConfigSection.tsx +266 -0
- package/src/modules/shipment_tracking/components/TimestampCell.tsx +146 -0
- package/src/modules/shipment_tracking/components/TrackingJobDrawer.tsx +467 -0
- package/src/modules/shipment_tracking/components/VesselTrackingMap.tsx +761 -0
- package/src/modules/shipment_tracking/components/WebhookDrawer.tsx +434 -0
- package/src/modules/shipment_tracking/data/entities.ts +748 -0
- package/src/modules/shipment_tracking/data/validators.ts +523 -0
- package/src/modules/shipment_tracking/di.ts +73 -0
- package/src/modules/shipment_tracking/encryption.ts +17 -0
- package/src/modules/shipment_tracking/events.ts +122 -0
- package/src/modules/shipment_tracking/hooks/useVesselTracking.ts +297 -0
- package/src/modules/shipment_tracking/i18n/de.json +327 -0
- package/src/modules/shipment_tracking/i18n/en.json +327 -0
- package/src/modules/shipment_tracking/i18n/es.json +327 -0
- package/src/modules/shipment_tracking/i18n/pl.json +327 -0
- package/src/modules/shipment_tracking/index.ts +13 -0
- package/src/modules/shipment_tracking/lib/__tests__/dcsa-event-mapping.test.ts +385 -0
- package/src/modules/shipment_tracking/lib/__tests__/dcsa-event-parser.test.ts +398 -0
- package/src/modules/shipment_tracking/lib/__tests__/empty-return.test.ts +174 -0
- package/src/modules/shipment_tracking/lib/__tests__/poi-event-processor.test.ts +699 -0
- package/src/modules/shipment_tracking/lib/__tests__/route-inference.test.ts +402 -0
- package/src/modules/shipment_tracking/lib/__tests__/status-machine.test.ts +447 -0
- package/src/modules/shipment_tracking/lib/__tests__/time-extraction.test.ts +331 -0
- package/src/modules/shipment_tracking/lib/__tests__/timestamp-utils.test.ts +260 -0
- package/src/modules/shipment_tracking/lib/__tests__/vessel-api.test.ts +125 -0
- package/src/modules/shipment_tracking/lib/__tests__/vessel-extraction.test.ts +108 -0
- package/src/modules/shipment_tracking/lib/adapters/cma-cgm.ts +84 -0
- package/src/modules/shipment_tracking/lib/adapters/cosco-types.ts +145 -0
- package/src/modules/shipment_tracking/lib/adapters/cosco.ts +314 -0
- package/src/modules/shipment_tracking/lib/adapters/evergreen.ts +107 -0
- package/src/modules/shipment_tracking/lib/adapters/hapag-lloyd.ts +88 -0
- package/src/modules/shipment_tracking/lib/adapters/index.ts +18 -0
- package/src/modules/shipment_tracking/lib/adapters/maersk.ts +104 -0
- package/src/modules/shipment_tracking/lib/adapters/msc.ts +223 -0
- package/src/modules/shipment_tracking/lib/adapters/zim.ts +106 -0
- package/src/modules/shipment_tracking/lib/audit-helpers.ts +29 -0
- package/src/modules/shipment_tracking/lib/auth/base64url.ts +4 -0
- package/src/modules/shipment_tracking/lib/auth/oauth-client.ts +53 -0
- package/src/modules/shipment_tracking/lib/background.ts +24 -0
- package/src/modules/shipment_tracking/lib/bic-api-client.ts +199 -0
- package/src/modules/shipment_tracking/lib/carrier-adapter.ts +136 -0
- package/src/modules/shipment_tracking/lib/current-vessel.ts +274 -0
- package/src/modules/shipment_tracking/lib/dcsa-event-mapping.ts +202 -0
- package/src/modules/shipment_tracking/lib/dcsa-event-parser.ts +163 -0
- package/src/modules/shipment_tracking/lib/dcsa-params.ts +14 -0
- package/src/modules/shipment_tracking/lib/empty-return.ts +122 -0
- package/src/modules/shipment_tracking/lib/location-overrides.ts +150 -0
- package/src/modules/shipment_tracking/lib/location-types.ts +154 -0
- package/src/modules/shipment_tracking/lib/logger.ts +195 -0
- package/src/modules/shipment_tracking/lib/poi-event-processor.ts +302 -0
- package/src/modules/shipment_tracking/lib/poi-nats-config.ts +134 -0
- package/src/modules/shipment_tracking/lib/poi-types.ts +198 -0
- package/src/modules/shipment_tracking/lib/rate-limiter.ts +58 -0
- package/src/modules/shipment_tracking/lib/route-extraction.ts +439 -0
- package/src/modules/shipment_tracking/lib/route-inference.ts +238 -0
- package/src/modules/shipment_tracking/lib/schedule-generator.ts +92 -0
- package/src/modules/shipment_tracking/lib/shipsgo-client.ts +350 -0
- package/src/modules/shipment_tracking/lib/shipsgo-mapper.ts +296 -0
- package/src/modules/shipment_tracking/lib/status-machine.ts +230 -0
- package/src/modules/shipment_tracking/lib/time-extraction.ts +85 -0
- package/src/modules/shipment_tracking/lib/timestamp-utils.ts +244 -0
- package/src/modules/shipment_tracking/lib/vessel-api.ts +299 -0
- package/src/modules/shipment_tracking/lib/vessel-cache.ts +102 -0
- package/src/modules/shipment_tracking/lib/vessel-extraction.ts +39 -0
- package/src/modules/shipment_tracking/lib/webhook-dispatcher.ts +93 -0
- package/src/modules/shipment_tracking/migrations/.snapshot-open-mercato.json +2914 -0
- package/src/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.ts +60 -0
- package/src/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.ts +22 -0
- package/src/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.ts +65 -0
- package/src/modules/shipment_tracking/notifications.ts +151 -0
- package/src/modules/shipment_tracking/services/carrierRegistry.ts +29 -0
- package/src/modules/shipment_tracking/services/poiNatsService.ts +526 -0
- package/src/modules/shipment_tracking/services/shipsGoProvider.ts +231 -0
- package/src/modules/shipment_tracking/services/trackingService.ts +1777 -0
- package/src/modules/shipment_tracking/services/webhookService.ts +347 -0
- package/src/modules/shipment_tracking/setup.ts +99 -0
- package/src/modules/shipment_tracking/subscribers/__tests__/terminal-event-ingest.test.ts +141 -0
- package/src/modules/shipment_tracking/subscribers/cargo-event-created.ts +115 -0
- package/src/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.ts +115 -0
- package/src/modules/shipment_tracking/subscribers/poi-event-notification.ts +144 -0
- package/src/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.ts +94 -0
- package/src/modules/shipment_tracking/subscribers/shipment-status-changed.ts +41 -0
- package/src/modules/shipment_tracking/subscribers/terminal-event-ingest.ts +109 -0
- package/src/modules/shipment_tracking/subscribers/tracking-job-initial-poll.ts +53 -0
- package/src/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.ts +50 -0
- package/src/modules/shipment_tracking/tables/index.ts +4 -0
- package/src/modules/shipment_tracking/tables/tracking_job/table.client.tsx +337 -0
- package/src/modules/shipment_tracking/tables/tracking_job/table.ts +34 -0
- package/src/modules/shipment_tracking/widgets/dashboard/ships-map/config.ts +32 -0
- package/src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.tsx +448 -0
- package/src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.ts +25 -0
- package/src/types/assets.d.ts +5 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { GoogleMap, useJsApiLoader, MarkerF, InfoWindowF } from "@react-google-maps/api";
|
|
6
|
+
import { Ship, Anchor, X } from "lucide-react";
|
|
7
|
+
import { apiCall } from "@freighttech/ui/backend/utils/apiCall";
|
|
8
|
+
import { Spinner } from "@freighttech/ui/primitives/spinner";
|
|
9
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
10
|
+
import { DEFAULT_SETTINGS, hydrateShipsMapSettings } from "./config.js";
|
|
11
|
+
const containerStyle = { width: "100%", height: "100%" };
|
|
12
|
+
const mapOptions = {
|
|
13
|
+
zoomControl: true,
|
|
14
|
+
mapTypeControl: false,
|
|
15
|
+
scaleControl: false,
|
|
16
|
+
streetViewControl: false,
|
|
17
|
+
rotateControl: false,
|
|
18
|
+
fullscreenControl: false,
|
|
19
|
+
disableDefaultUI: false,
|
|
20
|
+
gestureHandling: "cooperative",
|
|
21
|
+
// Muted gray-pastel skin: soft slate water, near-white land, faint borders, hidden POIs/
|
|
22
|
+
// transit and road labels for an uncluttered overview tile.
|
|
23
|
+
styles: [
|
|
24
|
+
{ elementType: "geometry", stylers: [{ color: "#f3f4f6" }] },
|
|
25
|
+
{ elementType: "labels.text.fill", stylers: [{ color: "#9aa0a6" }] },
|
|
26
|
+
{ elementType: "labels.text.stroke", stylers: [{ color: "#ffffff" }, { weight: 2 }] },
|
|
27
|
+
{ featureType: "water", elementType: "geometry", stylers: [{ color: "#dde3ea" }] },
|
|
28
|
+
{ featureType: "water", elementType: "labels.text.fill", stylers: [{ color: "#aab2bd" }] },
|
|
29
|
+
{ featureType: "landscape", elementType: "geometry", stylers: [{ color: "#f1f2f4" }] },
|
|
30
|
+
{ featureType: "road", elementType: "geometry", stylers: [{ color: "#e7e9ed" }] },
|
|
31
|
+
{ featureType: "road", elementType: "labels", stylers: [{ visibility: "off" }] },
|
|
32
|
+
{ featureType: "administrative", elementType: "geometry.stroke", stylers: [{ color: "#d6d9df" }] },
|
|
33
|
+
{ featureType: "administrative.country", elementType: "geometry.stroke", stylers: [{ color: "#c6cad1" }] },
|
|
34
|
+
{ featureType: "administrative.land_parcel", stylers: [{ visibility: "off" }] },
|
|
35
|
+
{ featureType: "poi", stylers: [{ visibility: "off" }] },
|
|
36
|
+
{ featureType: "transit", stylers: [{ visibility: "off" }] }
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
const CONTAINER_SHIP_PATH = `
|
|
40
|
+
M 12 2 L 8 7 L 8 30 Q 8 32, 10 32 L 10 34 L 14 34 L 14 32 Q 16 32, 16 30 L 16 7 L 12 2 Z
|
|
41
|
+
M 10 32 L 10 36 L 14 36 L 14 32 Z
|
|
42
|
+
`;
|
|
43
|
+
async function loadShipsMap() {
|
|
44
|
+
const call = await apiCall("/api/shipment_tracking/dashboard/ships-map");
|
|
45
|
+
if (!call.ok) {
|
|
46
|
+
const message = typeof call.result?.error === "string" ? call.result.error : `Request failed with status ${call.status}`;
|
|
47
|
+
throw new Error(message);
|
|
48
|
+
}
|
|
49
|
+
return call.result ?? { markers: [], unresolvedCount: 0, generatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
50
|
+
}
|
|
51
|
+
function formatRelativeTime(dateString, t) {
|
|
52
|
+
if (!dateString) return "";
|
|
53
|
+
const date = new Date(dateString);
|
|
54
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
55
|
+
const diffMs = Date.now() - date.getTime();
|
|
56
|
+
const diffMinutes = Math.floor(diffMs / 6e4);
|
|
57
|
+
const diffHours = Math.floor(diffMinutes / 60);
|
|
58
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
59
|
+
if (diffMinutes < 1) return t("shipment_tracking.map.justNow", "Just now");
|
|
60
|
+
if (diffMinutes < 60) return t("shipment_tracking.map.minutesAgo", "{{count}} min ago", { count: diffMinutes });
|
|
61
|
+
if (diffHours < 24) return t("shipment_tracking.map.hoursAgo", "{{count}}h ago", { count: diffHours });
|
|
62
|
+
return t("shipment_tracking.map.daysAgo", "{{count}}d ago", { count: diffDays });
|
|
63
|
+
}
|
|
64
|
+
function markerKey(marker, index) {
|
|
65
|
+
return marker.kind === "vessel" ? `vessel:${marker.imo}` : `port:${marker.unlocode ?? index}`;
|
|
66
|
+
}
|
|
67
|
+
function SettingsPanel({
|
|
68
|
+
settings,
|
|
69
|
+
onSettingsChange
|
|
70
|
+
}) {
|
|
71
|
+
const t = useT();
|
|
72
|
+
const update = (patch) => onSettingsChange({ ...settings, ...patch });
|
|
73
|
+
const inputClass = "w-full rounded-md border border-border bg-background px-2 py-1 text-body-regular-sm text-foreground";
|
|
74
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
75
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1", children: [
|
|
76
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-medium-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.settings.zoom", "Default zoom") }),
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
"input",
|
|
79
|
+
{
|
|
80
|
+
type: "number",
|
|
81
|
+
min: 1,
|
|
82
|
+
max: 20,
|
|
83
|
+
value: settings.defaultZoom,
|
|
84
|
+
onChange: (e) => update({ defaultZoom: Number(e.target.value) }),
|
|
85
|
+
className: inputClass
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
90
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1", children: [
|
|
91
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-medium-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.settings.centerLat", "Center latitude") }),
|
|
92
|
+
/* @__PURE__ */ jsx(
|
|
93
|
+
"input",
|
|
94
|
+
{
|
|
95
|
+
type: "number",
|
|
96
|
+
step: "0.1",
|
|
97
|
+
value: settings.centerLat,
|
|
98
|
+
onChange: (e) => update({ centerLat: Number(e.target.value) }),
|
|
99
|
+
className: inputClass
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1", children: [
|
|
104
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-medium-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.settings.centerLng", "Center longitude") }),
|
|
105
|
+
/* @__PURE__ */ jsx(
|
|
106
|
+
"input",
|
|
107
|
+
{
|
|
108
|
+
type: "number",
|
|
109
|
+
step: "0.1",
|
|
110
|
+
value: settings.centerLng,
|
|
111
|
+
onChange: (e) => update({ centerLng: Number(e.target.value) }),
|
|
112
|
+
className: inputClass
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] })
|
|
116
|
+
] }),
|
|
117
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1", children: [
|
|
118
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-medium-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.settings.autoRefresh", "Auto-refresh (seconds, 0 = off)") }),
|
|
119
|
+
/* @__PURE__ */ jsx(
|
|
120
|
+
"input",
|
|
121
|
+
{
|
|
122
|
+
type: "number",
|
|
123
|
+
min: 0,
|
|
124
|
+
value: settings.autoRefreshSeconds,
|
|
125
|
+
onChange: (e) => update({ autoRefreshSeconds: Number(e.target.value) }),
|
|
126
|
+
className: inputClass
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] })
|
|
130
|
+
] });
|
|
131
|
+
}
|
|
132
|
+
const ShipsMapWidget = ({
|
|
133
|
+
mode,
|
|
134
|
+
settings,
|
|
135
|
+
onSettingsChange,
|
|
136
|
+
refreshToken,
|
|
137
|
+
onRefreshStateChange
|
|
138
|
+
}) => {
|
|
139
|
+
const t = useT();
|
|
140
|
+
const hydrated = React.useMemo(() => hydrateShipsMapSettings(settings ?? DEFAULT_SETTINGS), [settings]);
|
|
141
|
+
const { isLoaded, loadError } = useJsApiLoader({
|
|
142
|
+
id: "google-map-script",
|
|
143
|
+
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || ""
|
|
144
|
+
});
|
|
145
|
+
const [data, setData] = React.useState(null);
|
|
146
|
+
const [loading, setLoading] = React.useState(true);
|
|
147
|
+
const [error, setError] = React.useState(null);
|
|
148
|
+
const [map, setMap] = React.useState(null);
|
|
149
|
+
const [selected, setSelected] = React.useState(null);
|
|
150
|
+
const refresh = React.useCallback(async () => {
|
|
151
|
+
onRefreshStateChange?.(true);
|
|
152
|
+
setLoading(true);
|
|
153
|
+
setError(null);
|
|
154
|
+
try {
|
|
155
|
+
setData(await loadShipsMap());
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.error("Failed to load ships map widget data", err);
|
|
158
|
+
setError(t("shipment_tracking.dashboard.ships_map.error", "Failed to load ships map"));
|
|
159
|
+
} finally {
|
|
160
|
+
setLoading(false);
|
|
161
|
+
onRefreshStateChange?.(false);
|
|
162
|
+
}
|
|
163
|
+
}, [onRefreshStateChange, t]);
|
|
164
|
+
React.useEffect(() => {
|
|
165
|
+
if (mode === "settings") return;
|
|
166
|
+
refresh().catch(() => {
|
|
167
|
+
});
|
|
168
|
+
}, [refresh, refreshToken, mode]);
|
|
169
|
+
React.useEffect(() => {
|
|
170
|
+
if (mode === "settings") return;
|
|
171
|
+
if (!hydrated.autoRefreshSeconds || hydrated.autoRefreshSeconds <= 0) return;
|
|
172
|
+
const id = setInterval(() => {
|
|
173
|
+
refresh().catch(() => {
|
|
174
|
+
});
|
|
175
|
+
}, hydrated.autoRefreshSeconds * 1e3);
|
|
176
|
+
return () => clearInterval(id);
|
|
177
|
+
}, [hydrated.autoRefreshSeconds, refresh, mode]);
|
|
178
|
+
React.useEffect(() => {
|
|
179
|
+
if (!map || !isLoaded || typeof window === "undefined") return;
|
|
180
|
+
const markers2 = data?.markers ?? [];
|
|
181
|
+
if (markers2.length === 0) return;
|
|
182
|
+
const google = window.google;
|
|
183
|
+
if (!google) return;
|
|
184
|
+
if (markers2.length === 1) {
|
|
185
|
+
map.setCenter(markers2[0].position);
|
|
186
|
+
map.setZoom(Math.max(hydrated.defaultZoom, 5));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const bounds = new google.maps.LatLngBounds();
|
|
190
|
+
markers2.forEach((m) => bounds.extend(m.position));
|
|
191
|
+
map.fitBounds(bounds, 48);
|
|
192
|
+
}, [map, isLoaded, data, hydrated.defaultZoom]);
|
|
193
|
+
const shipIconFactory = React.useCallback(
|
|
194
|
+
(heading) => {
|
|
195
|
+
if (!isLoaded || typeof window === "undefined") return void 0;
|
|
196
|
+
const google = window.google;
|
|
197
|
+
if (!google) return void 0;
|
|
198
|
+
return {
|
|
199
|
+
path: CONTAINER_SHIP_PATH,
|
|
200
|
+
fillColor: "#0f172a",
|
|
201
|
+
fillOpacity: 0.95,
|
|
202
|
+
strokeColor: "#ffffff",
|
|
203
|
+
strokeWeight: 1.5,
|
|
204
|
+
scale: 1,
|
|
205
|
+
rotation: heading ?? 0,
|
|
206
|
+
anchor: new google.maps.Point(12, 18)
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
[isLoaded]
|
|
210
|
+
);
|
|
211
|
+
const portIcon = React.useMemo(() => {
|
|
212
|
+
if (!isLoaded || typeof window === "undefined") return void 0;
|
|
213
|
+
const google = window.google;
|
|
214
|
+
if (!google) return void 0;
|
|
215
|
+
return {
|
|
216
|
+
path: google.maps.SymbolPath.CIRCLE,
|
|
217
|
+
scale: 7,
|
|
218
|
+
fillColor: "#059669",
|
|
219
|
+
fillOpacity: 0.95,
|
|
220
|
+
strokeColor: "#ffffff",
|
|
221
|
+
strokeWeight: 2
|
|
222
|
+
};
|
|
223
|
+
}, [isLoaded]);
|
|
224
|
+
const infoWindowOptions = React.useMemo(() => {
|
|
225
|
+
if (!isLoaded || typeof window === "undefined") return void 0;
|
|
226
|
+
const google = window.google;
|
|
227
|
+
if (!google) return void 0;
|
|
228
|
+
return { headerDisabled: true, pixelOffset: new google.maps.Size(0, -6), maxWidth: 280 };
|
|
229
|
+
}, [isLoaded]);
|
|
230
|
+
if (mode === "settings") {
|
|
231
|
+
return /* @__PURE__ */ jsx(SettingsPanel, { settings: hydrated, onSettingsChange });
|
|
232
|
+
}
|
|
233
|
+
if (loadError) {
|
|
234
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center rounded-lg border border-border bg-muted", children: /* @__PURE__ */ jsx("p", { className: "text-body-regular-sm text-muted-foreground", children: t("shipment_tracking.map.loadError", "Failed to load map") }) });
|
|
235
|
+
}
|
|
236
|
+
if (error) {
|
|
237
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center rounded-lg border border-border bg-muted", children: /* @__PURE__ */ jsx("p", { className: "text-body-regular-sm text-destructive", children: error }) });
|
|
238
|
+
}
|
|
239
|
+
const markers = data?.markers ?? [];
|
|
240
|
+
const vesselCount = markers.filter((m) => m.kind === "vessel").length;
|
|
241
|
+
const showSpinner = !isLoaded || loading && !data;
|
|
242
|
+
const isEmpty = !showSpinner && markers.length === 0;
|
|
243
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
244
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
245
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-body-medium-sm text-foreground", children: [
|
|
246
|
+
/* @__PURE__ */ jsx(Ship, { className: "h-4 w-4 text-blue-500" }),
|
|
247
|
+
/* @__PURE__ */ jsx("span", { children: t("shipment_tracking.dashboard.ships_map.vesselCount", "{{count}} ships", { count: vesselCount }) })
|
|
248
|
+
] }),
|
|
249
|
+
data && data.unresolvedCount > 0 && /* @__PURE__ */ jsx("span", { className: "text-body-regular-xs text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.unresolved", "{{count}} without position", {
|
|
250
|
+
count: data.unresolvedCount
|
|
251
|
+
}) })
|
|
252
|
+
] }),
|
|
253
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-72 overflow-hidden rounded-lg border border-border", children: [
|
|
254
|
+
showSpinner && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 bg-muted", children: [
|
|
255
|
+
/* @__PURE__ */ jsx(Spinner, { className: "h-6 w-6" }),
|
|
256
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-regular-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.loading", "Loading map\u2026") })
|
|
257
|
+
] }),
|
|
258
|
+
isEmpty && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 bg-muted", children: [
|
|
259
|
+
/* @__PURE__ */ jsx(Ship, { className: "h-8 w-8 text-muted-foreground" }),
|
|
260
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-regular-sm text-muted-foreground", children: t("shipment_tracking.dashboard.ships_map.empty", "No active vessels") })
|
|
261
|
+
] }),
|
|
262
|
+
isLoaded && /* @__PURE__ */ jsxs(
|
|
263
|
+
GoogleMap,
|
|
264
|
+
{
|
|
265
|
+
mapContainerStyle: containerStyle,
|
|
266
|
+
center: { lat: hydrated.centerLat, lng: hydrated.centerLng },
|
|
267
|
+
zoom: hydrated.defaultZoom,
|
|
268
|
+
onLoad: (m) => setMap(m),
|
|
269
|
+
onUnmount: () => setMap(null),
|
|
270
|
+
options: mapOptions,
|
|
271
|
+
children: [
|
|
272
|
+
markers.map((marker, index) => {
|
|
273
|
+
const key = markerKey(marker, index);
|
|
274
|
+
return /* @__PURE__ */ jsx(
|
|
275
|
+
MarkerF,
|
|
276
|
+
{
|
|
277
|
+
position: marker.position,
|
|
278
|
+
icon: marker.kind === "vessel" ? shipIconFactory(marker.heading) : portIcon,
|
|
279
|
+
title: marker.kind === "vessel" ? marker.name ?? marker.imo : marker.portName ?? void 0,
|
|
280
|
+
zIndex: marker.kind === "vessel" ? 2e3 : 1e3,
|
|
281
|
+
onClick: () => setSelected(key)
|
|
282
|
+
},
|
|
283
|
+
key
|
|
284
|
+
);
|
|
285
|
+
}),
|
|
286
|
+
markers.map((marker, index) => {
|
|
287
|
+
const key = markerKey(marker, index);
|
|
288
|
+
if (selected !== key) return null;
|
|
289
|
+
return /* @__PURE__ */ jsx(
|
|
290
|
+
InfoWindowF,
|
|
291
|
+
{
|
|
292
|
+
position: marker.position,
|
|
293
|
+
onCloseClick: () => setSelected(null),
|
|
294
|
+
options: infoWindowOptions,
|
|
295
|
+
children: /* @__PURE__ */ jsxs("div", { className: "relative min-w-[180px] max-w-[260px] pr-5 text-slate-800", children: [
|
|
296
|
+
/* @__PURE__ */ jsx(
|
|
297
|
+
"button",
|
|
298
|
+
{
|
|
299
|
+
type: "button",
|
|
300
|
+
onClick: () => setSelected(null),
|
|
301
|
+
"aria-label": t("shipment_tracking.map.close", "Close"),
|
|
302
|
+
className: "absolute right-0 top-0 flex h-5 w-5 items-center justify-center rounded text-slate-400 hover:bg-slate-100 hover:text-slate-700",
|
|
303
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
marker.kind === "vessel" ? /* @__PURE__ */ jsxs("div", { className: "mb-1.5", children: [
|
|
307
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
308
|
+
/* @__PURE__ */ jsx(Ship, { className: "h-3.5 w-3.5 text-blue-500" }),
|
|
309
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold leading-tight text-slate-900", children: marker.name ?? t("shipment_tracking.map.unknown", "Unknown") })
|
|
310
|
+
] }),
|
|
311
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 font-mono text-[11px] text-slate-400", children: [
|
|
312
|
+
"IMO ",
|
|
313
|
+
marker.imo
|
|
314
|
+
] }),
|
|
315
|
+
marker.destination && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 text-xs text-slate-500", children: [
|
|
316
|
+
"\u2192 ",
|
|
317
|
+
marker.destination
|
|
318
|
+
] }),
|
|
319
|
+
marker.updatedAt && /* @__PURE__ */ jsx("div", { className: "text-[11px] text-slate-400", children: formatRelativeTime(marker.updatedAt, t) })
|
|
320
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "mb-1.5", children: [
|
|
321
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
322
|
+
/* @__PURE__ */ jsx(Anchor, { className: "h-3.5 w-3.5 text-emerald-600" }),
|
|
323
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold leading-tight text-slate-900", children: marker.portName ?? t("shipment_tracking.map.unknown", "Unknown") })
|
|
324
|
+
] }),
|
|
325
|
+
marker.unlocode && /* @__PURE__ */ jsx("div", { className: "mt-0.5 font-mono text-[11px] text-slate-400", children: marker.unlocode })
|
|
326
|
+
] }),
|
|
327
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-0.5 border-t border-slate-100 pt-1.5", children: marker.shipments.map((s) => /* @__PURE__ */ jsxs(
|
|
328
|
+
Link,
|
|
329
|
+
{
|
|
330
|
+
href: `/backend/shipment-tracking?shipment=${s.id}`,
|
|
331
|
+
className: "block truncate text-xs text-blue-600 hover:underline",
|
|
332
|
+
title: s.containerNumber ?? s.id,
|
|
333
|
+
children: [
|
|
334
|
+
s.containerNumber ?? s.id,
|
|
335
|
+
s.destinationLocation ? ` \xB7 ${s.destinationLocation}` : ""
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
s.id
|
|
339
|
+
)) })
|
|
340
|
+
] })
|
|
341
|
+
},
|
|
342
|
+
`iw:${key}`
|
|
343
|
+
);
|
|
344
|
+
})
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
)
|
|
348
|
+
] })
|
|
349
|
+
] });
|
|
350
|
+
};
|
|
351
|
+
var widget_client_default = ShipsMapWidget;
|
|
352
|
+
export {
|
|
353
|
+
widget_client_default as default
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=widget.client.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\n/**\n * Ships Map dashboard widget \u2014 fleet-level overview of every vessel currently carrying the\n * organization's tracked containers, plus ports where at-rest cargo waits. Read-only overlay\n * over the `shipment_tracking.dashboard.ships_map` aggregation route.\n */\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { GoogleMap, useJsApiLoader, MarkerF, InfoWindowF } from '@react-google-maps/api'\nimport { Ship, Anchor, X } from 'lucide-react'\nimport type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'\nimport { apiCall } from '@freighttech/ui/backend/utils/apiCall'\nimport { Spinner } from '@freighttech/ui/primitives/spinner'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { ShipsMapResponse, ShipsMapMarker } from '../../../data/validators'\nimport { DEFAULT_SETTINGS, hydrateShipsMapSettings, type ShipsMapSettings } from './config'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype GoogleMapInstance = any\n\n// \u2500\u2500\u2500 Map configuration (shared look with VesselTrackingMap) \u2500\u2500\n\nconst containerStyle: React.CSSProperties = { width: '100%', height: '100%' }\n\nconst mapOptions: Record<string, unknown> = {\n zoomControl: true,\n mapTypeControl: false,\n scaleControl: false,\n streetViewControl: false,\n rotateControl: false,\n fullscreenControl: false,\n disableDefaultUI: false,\n gestureHandling: 'cooperative',\n // Muted gray-pastel skin: soft slate water, near-white land, faint borders, hidden POIs/\n // transit and road labels for an uncluttered overview tile.\n styles: [\n { elementType: 'geometry', stylers: [{ color: '#f3f4f6' }] },\n { elementType: 'labels.text.fill', stylers: [{ color: '#9aa0a6' }] },\n { elementType: 'labels.text.stroke', stylers: [{ color: '#ffffff' }, { weight: 2 }] },\n { featureType: 'water', elementType: 'geometry', stylers: [{ color: '#dde3ea' }] },\n { featureType: 'water', elementType: 'labels.text.fill', stylers: [{ color: '#aab2bd' }] },\n { featureType: 'landscape', elementType: 'geometry', stylers: [{ color: '#f1f2f4' }] },\n { featureType: 'road', elementType: 'geometry', stylers: [{ color: '#e7e9ed' }] },\n { featureType: 'road', elementType: 'labels', stylers: [{ visibility: 'off' }] },\n { featureType: 'administrative', elementType: 'geometry.stroke', stylers: [{ color: '#d6d9df' }] },\n { featureType: 'administrative.country', elementType: 'geometry.stroke', stylers: [{ color: '#c6cad1' }] },\n { featureType: 'administrative.land_parcel', stylers: [{ visibility: 'off' }] },\n { featureType: 'poi', stylers: [{ visibility: 'off' }] },\n { featureType: 'transit', stylers: [{ visibility: 'off' }] },\n ],\n}\n\n// Top-down container-ship silhouette (pointing north), shared with VesselTrackingMap.\nconst CONTAINER_SHIP_PATH = `\n M 12 2 L 8 7 L 8 30 Q 8 32, 10 32 L 10 34 L 14 34 L 14 32 Q 16 32, 16 30 L 16 7 L 12 2 Z\n M 10 32 L 10 36 L 14 36 L 14 32 Z\n`\n\n// \u2500\u2500\u2500 Data loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function loadShipsMap(): Promise<ShipsMapResponse> {\n const call = await apiCall<ShipsMapResponse>('/api/shipment_tracking/dashboard/ships-map')\n if (!call.ok) {\n const message =\n typeof (call.result as Record<string, unknown> | null)?.error === 'string'\n ? ((call.result as Record<string, unknown>).error as string)\n : `Request failed with status ${call.status}`\n throw new Error(message)\n }\n return call.result ?? { markers: [], unresolvedCount: 0, generatedAt: new Date().toISOString() }\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction formatRelativeTime(dateString: string | null, t: ReturnType<typeof useT>): string {\n if (!dateString) return ''\n const date = new Date(dateString)\n if (Number.isNaN(date.getTime())) return ''\n const diffMs = Date.now() - date.getTime()\n const diffMinutes = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMinutes / 60)\n const diffDays = Math.floor(diffHours / 24)\n if (diffMinutes < 1) return t('shipment_tracking.map.justNow', 'Just now')\n if (diffMinutes < 60) return t('shipment_tracking.map.minutesAgo', '{{count}} min ago', { count: diffMinutes })\n if (diffHours < 24) return t('shipment_tracking.map.hoursAgo', '{{count}}h ago', { count: diffHours })\n return t('shipment_tracking.map.daysAgo', '{{count}}d ago', { count: diffDays })\n}\n\nfunction markerKey(marker: ShipsMapMarker, index: number): string {\n return marker.kind === 'vessel' ? `vessel:${marker.imo}` : `port:${marker.unlocode ?? index}`\n}\n\n// \u2500\u2500\u2500 Settings panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction SettingsPanel({\n settings,\n onSettingsChange,\n}: {\n settings: ShipsMapSettings\n onSettingsChange: (next: ShipsMapSettings) => void\n}) {\n const t = useT()\n const update = (patch: Partial<ShipsMapSettings>) => onSettingsChange({ ...settings, ...patch })\n const inputClass =\n 'w-full rounded-md border border-border bg-background px-2 py-1 text-body-regular-sm text-foreground'\n return (\n <div className=\"space-y-3\">\n <label className=\"block space-y-1\">\n <span className=\"text-body-medium-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.settings.zoom', 'Default zoom')}\n </span>\n <input\n type=\"number\"\n min={1}\n max={20}\n value={settings.defaultZoom}\n onChange={(e) => update({ defaultZoom: Number(e.target.value) })}\n className={inputClass}\n />\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block space-y-1\">\n <span className=\"text-body-medium-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.settings.centerLat', 'Center latitude')}\n </span>\n <input\n type=\"number\"\n step=\"0.1\"\n value={settings.centerLat}\n onChange={(e) => update({ centerLat: Number(e.target.value) })}\n className={inputClass}\n />\n </label>\n <label className=\"block space-y-1\">\n <span className=\"text-body-medium-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.settings.centerLng', 'Center longitude')}\n </span>\n <input\n type=\"number\"\n step=\"0.1\"\n value={settings.centerLng}\n onChange={(e) => update({ centerLng: Number(e.target.value) })}\n className={inputClass}\n />\n </label>\n </div>\n <label className=\"block space-y-1\">\n <span className=\"text-body-medium-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.settings.autoRefresh', 'Auto-refresh (seconds, 0 = off)')}\n </span>\n <input\n type=\"number\"\n min={0}\n value={settings.autoRefreshSeconds}\n onChange={(e) => update({ autoRefreshSeconds: Number(e.target.value) })}\n className={inputClass}\n />\n </label>\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ShipsMapWidget: React.FC<DashboardWidgetComponentProps<ShipsMapSettings>> = ({\n mode,\n settings,\n onSettingsChange,\n refreshToken,\n onRefreshStateChange,\n}) => {\n const t = useT()\n const hydrated = React.useMemo(() => hydrateShipsMapSettings(settings ?? DEFAULT_SETTINGS), [settings])\n\n const { isLoaded, loadError } = useJsApiLoader({\n id: 'google-map-script',\n googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || '',\n })\n\n const [data, setData] = React.useState<ShipsMapResponse | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [map, setMap] = React.useState<GoogleMapInstance | null>(null)\n const [selected, setSelected] = React.useState<string | null>(null)\n\n const refresh = React.useCallback(async () => {\n onRefreshStateChange?.(true)\n setLoading(true)\n setError(null)\n try {\n setData(await loadShipsMap())\n } catch (err) {\n console.error('Failed to load ships map widget data', err)\n setError(t('shipment_tracking.dashboard.ships_map.error', 'Failed to load ships map'))\n } finally {\n setLoading(false)\n onRefreshStateChange?.(false)\n }\n }, [onRefreshStateChange, t])\n\n // Initial load + manual refresh via the card's refresh button.\n React.useEffect(() => {\n if (mode === 'settings') return\n refresh().catch(() => {})\n }, [refresh, refreshToken, mode])\n\n // Auto-refresh.\n React.useEffect(() => {\n if (mode === 'settings') return\n if (!hydrated.autoRefreshSeconds || hydrated.autoRefreshSeconds <= 0) return\n const id = setInterval(() => {\n refresh().catch(() => {})\n }, hydrated.autoRefreshSeconds * 1000)\n return () => clearInterval(id)\n }, [hydrated.autoRefreshSeconds, refresh, mode])\n\n // Fit bounds to all markers once the map and data are ready.\n React.useEffect(() => {\n if (!map || !isLoaded || typeof window === 'undefined') return\n const markers = data?.markers ?? []\n if (markers.length === 0) return\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const google = (window as any).google\n if (!google) return\n if (markers.length === 1) {\n map.setCenter(markers[0].position)\n map.setZoom(Math.max(hydrated.defaultZoom, 5))\n return\n }\n const bounds = new google.maps.LatLngBounds()\n markers.forEach((m) => bounds.extend(m.position))\n map.fitBounds(bounds, 48)\n }, [map, isLoaded, data, hydrated.defaultZoom])\n\n const shipIconFactory = React.useCallback(\n (heading: number | null) => {\n if (!isLoaded || typeof window === 'undefined') return undefined\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const google = (window as any).google\n if (!google) return undefined\n return {\n path: CONTAINER_SHIP_PATH,\n fillColor: '#0f172a',\n fillOpacity: 0.95,\n strokeColor: '#ffffff',\n strokeWeight: 1.5,\n scale: 1.0,\n rotation: heading ?? 0,\n anchor: new google.maps.Point(12, 18),\n }\n },\n [isLoaded],\n )\n\n const portIcon = React.useMemo(() => {\n if (!isLoaded || typeof window === 'undefined') return undefined\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const google = (window as any).google\n if (!google) return undefined\n return {\n path: google.maps.SymbolPath.CIRCLE,\n scale: 7,\n fillColor: '#059669',\n fillOpacity: 0.95,\n strokeColor: '#ffffff',\n strokeWeight: 2,\n }\n }, [isLoaded])\n\n const infoWindowOptions = React.useMemo(() => {\n if (!isLoaded || typeof window === 'undefined') return undefined\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const google = (window as any).google\n if (!google) return undefined\n return { headerDisabled: true, pixelOffset: new google.maps.Size(0, -6), maxWidth: 280 }\n }, [isLoaded])\n\n // \u2500\u2500\u2500 Settings mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (mode === 'settings') {\n return <SettingsPanel settings={hydrated} onSettingsChange={onSettingsChange} />\n }\n\n // \u2500\u2500\u2500 Error / map-load states \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (loadError) {\n return (\n <div className=\"flex h-64 items-center justify-center rounded-lg border border-border bg-muted\">\n <p className=\"text-body-regular-sm text-muted-foreground\">\n {t('shipment_tracking.map.loadError', 'Failed to load map')}\n </p>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"flex h-64 items-center justify-center rounded-lg border border-border bg-muted\">\n <p className=\"text-body-regular-sm text-destructive\">{error}</p>\n </div>\n )\n }\n\n const markers = data?.markers ?? []\n const vesselCount = markers.filter((m) => m.kind === 'vessel').length\n const showSpinner = !isLoaded || (loading && !data)\n const isEmpty = !showSpinner && markers.length === 0\n\n return (\n <div className=\"space-y-2\">\n {/* Header: counts + unresolved hint */}\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1.5 text-body-medium-sm text-foreground\">\n <Ship className=\"h-4 w-4 text-blue-500\" />\n <span>\n {t('shipment_tracking.dashboard.ships_map.vesselCount', '{{count}} ships', { count: vesselCount })}\n </span>\n </div>\n {data && data.unresolvedCount > 0 && (\n <span className=\"text-body-regular-xs text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.unresolved', '{{count}} without position', {\n count: data.unresolvedCount,\n })}\n </span>\n )}\n </div>\n\n <div className=\"relative h-72 overflow-hidden rounded-lg border border-border\">\n {showSpinner && (\n <div className=\"absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 bg-muted\">\n <Spinner className=\"h-6 w-6\" />\n <span className=\"text-body-regular-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.loading', 'Loading map\u2026')}\n </span>\n </div>\n )}\n\n {isEmpty && (\n <div className=\"absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 bg-muted\">\n <Ship className=\"h-8 w-8 text-muted-foreground\" />\n <span className=\"text-body-regular-sm text-muted-foreground\">\n {t('shipment_tracking.dashboard.ships_map.empty', 'No active vessels')}\n </span>\n </div>\n )}\n\n {isLoaded && (\n <GoogleMap\n mapContainerStyle={containerStyle}\n center={{ lat: hydrated.centerLat, lng: hydrated.centerLng }}\n zoom={hydrated.defaultZoom}\n onLoad={(m) => setMap(m)}\n onUnmount={() => setMap(null)}\n options={mapOptions}\n >\n {markers.map((marker, index) => {\n const key = markerKey(marker, index)\n return (\n <MarkerF\n key={key}\n position={marker.position}\n icon={marker.kind === 'vessel' ? shipIconFactory(marker.heading) : portIcon}\n title={marker.kind === 'vessel' ? marker.name ?? marker.imo : marker.portName ?? undefined}\n zIndex={marker.kind === 'vessel' ? 2000 : 1000}\n onClick={() => setSelected(key)}\n />\n )\n })}\n\n {markers.map((marker, index) => {\n const key = markerKey(marker, index)\n if (selected !== key) return null\n return (\n <InfoWindowF\n key={`iw:${key}`}\n position={marker.position}\n onCloseClick={() => setSelected(null)}\n options={infoWindowOptions}\n >\n <div className=\"relative min-w-[180px] max-w-[260px] pr-5 text-slate-800\">\n <button\n type=\"button\"\n onClick={() => setSelected(null)}\n aria-label={t('shipment_tracking.map.close', 'Close')}\n className=\"absolute right-0 top-0 flex h-5 w-5 items-center justify-center rounded text-slate-400 hover:bg-slate-100 hover:text-slate-700\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n\n {marker.kind === 'vessel' ? (\n <div className=\"mb-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Ship className=\"h-3.5 w-3.5 text-blue-500\" />\n <span className=\"text-sm font-semibold leading-tight text-slate-900\">\n {marker.name ?? t('shipment_tracking.map.unknown', 'Unknown')}\n </span>\n </div>\n <div className=\"mt-0.5 font-mono text-[11px] text-slate-400\">IMO {marker.imo}</div>\n {marker.destination && (\n <div className=\"mt-0.5 text-xs text-slate-500\">\u2192 {marker.destination}</div>\n )}\n {marker.updatedAt && (\n <div className=\"text-[11px] text-slate-400\">\n {formatRelativeTime(marker.updatedAt, t)}\n </div>\n )}\n </div>\n ) : (\n <div className=\"mb-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Anchor className=\"h-3.5 w-3.5 text-emerald-600\" />\n <span className=\"text-sm font-semibold leading-tight text-slate-900\">\n {marker.portName ?? t('shipment_tracking.map.unknown', 'Unknown')}\n </span>\n </div>\n {marker.unlocode && (\n <div className=\"mt-0.5 font-mono text-[11px] text-slate-400\">{marker.unlocode}</div>\n )}\n </div>\n )}\n\n <div className=\"space-y-0.5 border-t border-slate-100 pt-1.5\">\n {marker.shipments.map((s) => (\n <Link\n key={s.id}\n href={`/backend/shipment-tracking?shipment=${s.id}`}\n className=\"block truncate text-xs text-blue-600 hover:underline\"\n title={s.containerNumber ?? s.id}\n >\n {s.containerNumber ?? s.id}\n {s.destinationLocation ? ` \u00B7 ${s.destinationLocation}` : ''}\n </Link>\n ))}\n </div>\n </div>\n </InfoWindowF>\n )\n })}\n </GoogleMap>\n )}\n </div>\n </div>\n )\n}\n\nexport default ShipsMapWidget\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["markers"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { lazyDashboardWidget } from "@open-mercato/shared/modules/dashboard/widgets";
|
|
2
|
+
import { DEFAULT_SETTINGS, hydrateShipsMapSettings } from "./config.js";
|
|
3
|
+
const ShipsMapWidget = lazyDashboardWidget(() => import("./widget.client.js"));
|
|
4
|
+
const widget = {
|
|
5
|
+
metadata: {
|
|
6
|
+
id: "shipment_tracking.dashboard.ships_map",
|
|
7
|
+
title: "Ships Map",
|
|
8
|
+
description: "Live positions of every vessel carrying your tracked containers, on one map.",
|
|
9
|
+
features: ["dashboards.view", "shipment_tracking.dashboard.ships_map.view"],
|
|
10
|
+
defaultSize: "lg",
|
|
11
|
+
defaultEnabled: false,
|
|
12
|
+
defaultSettings: DEFAULT_SETTINGS,
|
|
13
|
+
tags: ["fms", "shipment_tracking", "map"],
|
|
14
|
+
category: "shipment_tracking",
|
|
15
|
+
icon: "ship",
|
|
16
|
+
supportsRefresh: true
|
|
17
|
+
},
|
|
18
|
+
Widget: ShipsMapWidget,
|
|
19
|
+
hydrateSettings: hydrateShipsMapSettings,
|
|
20
|
+
dehydrateSettings: (settings) => settings
|
|
21
|
+
};
|
|
22
|
+
var widget_default = widget;
|
|
23
|
+
export {
|
|
24
|
+
widget_default as default
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=widget.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.ts"],
|
|
4
|
+
"sourcesContent": ["import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'\nimport { DEFAULT_SETTINGS, hydrateShipsMapSettings, type ShipsMapSettings } from './config'\n\nconst ShipsMapWidget = lazyDashboardWidget(() => import('./widget.client'))\n\nconst widget: DashboardWidgetModule<ShipsMapSettings> = {\n metadata: {\n id: 'shipment_tracking.dashboard.ships_map',\n title: 'Ships Map',\n description: 'Live positions of every vessel carrying your tracked containers, on one map.',\n features: ['dashboards.view', 'shipment_tracking.dashboard.ships_map.view'],\n defaultSize: 'lg',\n defaultEnabled: false,\n defaultSettings: DEFAULT_SETTINGS,\n tags: ['fms', 'shipment_tracking', 'map'],\n category: 'shipment_tracking',\n icon: 'ship',\n supportsRefresh: true,\n },\n Widget: ShipsMapWidget,\n hydrateSettings: hydrateShipsMapSettings,\n dehydrateSettings: (settings) => settings,\n}\n\nexport default widget\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,2BAAuD;AAChE,SAAS,kBAAkB,+BAAsD;AAEjF,MAAM,iBAAiB,oBAAoB,MAAM,OAAO,iBAAiB,CAAC;AAE1E,MAAM,SAAkD;AAAA,EACtD,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,CAAC,mBAAmB,4CAA4C;AAAA,IAC1E,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,MAAM,CAAC,OAAO,qBAAqB,KAAK;AAAA,IACxC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,iBAAiB;AAAA,EACnB;AAAA,EACA,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,mBAAmB,CAAC,aAAa;AACnC;AAEA,IAAO,iBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=assets.d.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// One file per entity, named `toSnake(ClassName)` — NOT the table name. Each
|
|
4
|
+
// export is a database column name, mirroring what `mercato generate` writes
|
|
5
|
+
// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`
|
|
6
|
+
// reads these back to build the host app's `entity-fields-registry.ts`, which
|
|
7
|
+
// is what the Encryption and Translation managers list fields from.
|
|
8
|
+
//
|
|
9
|
+
// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package
|
|
10
|
+
// build does it for you. Guarded by
|
|
11
|
+
// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.
|
|
12
|
+
export const id = "id";
|
|
13
|
+
export const organization_id = "organization_id";
|
|
14
|
+
export const tenant_id = "tenant_id";
|
|
15
|
+
export const is_enabled = "is_enabled";
|
|
16
|
+
export const username = "username";
|
|
17
|
+
export const password = "password";
|
|
18
|
+
export const base_url = "base_url";
|
|
19
|
+
export const created_at = "created_at";
|
|
20
|
+
export const updated_at = "updated_at";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// One file per entity, named `toSnake(ClassName)` — NOT the table name. Each
|
|
4
|
+
// export is a database column name, mirroring what `mercato generate` writes
|
|
5
|
+
// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`
|
|
6
|
+
// reads these back to build the host app's `entity-fields-registry.ts`, which
|
|
7
|
+
// is what the Encryption and Translation managers list fields from.
|
|
8
|
+
//
|
|
9
|
+
// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package
|
|
10
|
+
// build does it for you. Guarded by
|
|
11
|
+
// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.
|
|
12
|
+
export const id = "id";
|
|
13
|
+
export const organization_id = "organization_id";
|
|
14
|
+
export const tenant_id = "tenant_id";
|
|
15
|
+
export const carrier_code = "carrier_code";
|
|
16
|
+
export const api_endpoint = "api_endpoint";
|
|
17
|
+
export const auth_config = "auth_config";
|
|
18
|
+
export const rate_limit_requests = "rate_limit_requests";
|
|
19
|
+
export const rate_limit_window_seconds = "rate_limit_window_seconds";
|
|
20
|
+
export const is_active = "is_active";
|
|
21
|
+
export const created_at = "created_at";
|
|
22
|
+
export const updated_at = "updated_at";
|
|
23
|
+
export const deleted_at = "deleted_at";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// One file per entity, named `toSnake(ClassName)` — NOT the table name. Each
|
|
4
|
+
// export is a database column name, mirroring what `mercato generate` writes
|
|
5
|
+
// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`
|
|
6
|
+
// reads these back to build the host app's `entity-fields-registry.ts`, which
|
|
7
|
+
// is what the Encryption and Translation managers list fields from.
|
|
8
|
+
//
|
|
9
|
+
// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package
|
|
10
|
+
// build does it for you. Guarded by
|
|
11
|
+
// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.
|
|
12
|
+
export const id = "id";
|
|
13
|
+
export const organization_id = "organization_id";
|
|
14
|
+
export const tenant_id = "tenant_id";
|
|
15
|
+
export const carrier_code = "carrier_code";
|
|
16
|
+
export const unlocode = "unlocode";
|
|
17
|
+
export const facility_code = "facility_code";
|
|
18
|
+
export const facility_code_list_provider = "facility_code_list_provider";
|
|
19
|
+
export const override_data = "override_data";
|
|
20
|
+
export const description = "description";
|
|
21
|
+
export const is_active = "is_active";
|
|
22
|
+
export const created_at = "created_at";
|
|
23
|
+
export const updated_at = "updated_at";
|
|
24
|
+
export const deleted_at = "deleted_at";
|
|
25
|
+
export const created_by_user_id = "created_by_user_id";
|
|
26
|
+
export const updated_by_user_id = "updated_by_user_id";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// One file per entity, named `toSnake(ClassName)` — NOT the table name. Each
|
|
4
|
+
// export is a database column name, mirroring what `mercato generate` writes
|
|
5
|
+
// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`
|
|
6
|
+
// reads these back to build the host app's `entity-fields-registry.ts`, which
|
|
7
|
+
// is what the Encryption and Translation managers list fields from.
|
|
8
|
+
//
|
|
9
|
+
// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package
|
|
10
|
+
// build does it for you. Guarded by
|
|
11
|
+
// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.
|
|
12
|
+
export const id = "id";
|
|
13
|
+
export const organization_id = "organization_id";
|
|
14
|
+
export const tenant_id = "tenant_id";
|
|
15
|
+
export const status = "status";
|
|
16
|
+
export const mode = "mode";
|
|
17
|
+
export const carrier_code = "carrier_code";
|
|
18
|
+
export const container_number = "container_number";
|
|
19
|
+
export const awb_number = "awb_number";
|
|
20
|
+
export const flight_number = "flight_number";
|
|
21
|
+
export const airline_code = "airline_code";
|
|
22
|
+
export const airline_name = "airline_name";
|
|
23
|
+
export const iso_equipment_code = "iso_equipment_code";
|
|
24
|
+
export const booking_number = "booking_number";
|
|
25
|
+
export const bol_number = "bol_number";
|
|
26
|
+
export const etd_timestamps = "etd_timestamps";
|
|
27
|
+
export const eta_timestamps = "eta_timestamps";
|
|
28
|
+
export const atd_timestamps = "atd_timestamps";
|
|
29
|
+
export const ata_timestamps = "ata_timestamps";
|
|
30
|
+
export const origin_location = "origin_location";
|
|
31
|
+
export const destination_location = "destination_location";
|
|
32
|
+
export const vessel_name = "vessel_name";
|
|
33
|
+
export const vessel_imo = "vessel_imo";
|
|
34
|
+
export const voyage_number = "voyage_number";
|
|
35
|
+
export const event_count = "event_count";
|
|
36
|
+
export const last_event_at = "last_event_at";
|
|
37
|
+
export const extra = "extra";
|
|
38
|
+
export const route_stops = "route_stops";
|
|
39
|
+
export const cargo_events = "cargo_events";
|
|
40
|
+
export const seals = "seals";
|
|
41
|
+
export const is_active = "is_active";
|
|
42
|
+
export const created_at = "created_at";
|
|
43
|
+
export const updated_at = "updated_at";
|
|
44
|
+
export const deleted_at = "deleted_at";
|
|
45
|
+
export const created_by_user_id = "created_by_user_id";
|
|
46
|
+
export const tracking_job = "tracking_job";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.
|
|
2
|
+
//
|
|
3
|
+
// One file per entity, named `toSnake(ClassName)` — NOT the table name. Each
|
|
4
|
+
// export is a database column name, mirroring what `mercato generate` writes
|
|
5
|
+
// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`
|
|
6
|
+
// reads these back to build the host app's `entity-fields-registry.ts`, which
|
|
7
|
+
// is what the Encryption and Translation managers list fields from.
|
|
8
|
+
//
|
|
9
|
+
// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package
|
|
10
|
+
// build does it for you. Guarded by
|
|
11
|
+
// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.
|
|
12
|
+
export const id = "id";
|
|
13
|
+
export const organization_id = "organization_id";
|
|
14
|
+
export const tenant_id = "tenant_id";
|
|
15
|
+
export const is_enabled = "is_enabled";
|
|
16
|
+
export const api_token = "api_token";
|
|
17
|
+
export const base_url = "base_url";
|
|
18
|
+
export const ocean_enabled = "ocean_enabled";
|
|
19
|
+
export const air_enabled = "air_enabled";
|
|
20
|
+
export const rate_limit_requests = "rate_limit_requests";
|
|
21
|
+
export const rate_limit_window_seconds = "rate_limit_window_seconds";
|
|
22
|
+
export const is_active = "is_active";
|
|
23
|
+
export const created_at = "created_at";
|
|
24
|
+
export const updated_at = "updated_at";
|
|
25
|
+
export const deleted_at = "deleted_at";
|