Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
78d8800
Reapply "Add Fleet-Ops AI operational query capabilities"
roncodes Jun 29, 2026
71e08fc
v0.6.57
roncodes Jun 29, 2026
51c86f0
Merge pull request #273 from fleetbase/feature/ai-operational-capabil…
roncodes Jun 29, 2026
1eea839
Polish Fleet-Ops AI order preview
roncodes Jun 30, 2026
81c5e6b
Merge branch 'dev-v0.6.57' into feature/ai-operational-capabilities
roncodes Jun 30, 2026
76d62c9
Merge pull request #275 from fleetbase/feature/ai-operational-capabil…
roncodes Jun 30, 2026
d012006
latest
roncodes Jun 30, 2026
3a6b58e
ran php-cs-fixer
roncodes Jun 30, 2026
7b164d9
Merge branch 'dev-v0.6.57' of github.com:fleetbase/fleetops into dev-…
roncodes Jun 30, 2026
a407394
Fix AI route preview map errors
roncodes Jun 30, 2026
d2f5e42
Polish AI create order preview
roncodes Jun 30, 2026
84f34e9
Fix AI route preview engine lookup
roncodes Jun 30, 2026
69c368d
Resolve relative dates in Fleet-Ops AI capabilities
roncodes Jun 30, 2026
52f795f
Stabilize AI order preview editing
roncodes Jun 30, 2026
1548082
Fix AI order preview map and schedule display
roncodes Jun 30, 2026
b2d2930
Use format-date-fns for AI preview schedule
roncodes Jun 30, 2026
2f21489
Fix AI route preview Google map lifecycle
roncodes Jul 1, 2026
48860b7
Fix AI order place point resolution
roncodes Jul 1, 2026
374a2c8
fix ai order creation capability and payload normalization
roncodes Jul 1, 2026
12ac1d9
upgraded dependencies
roncodes Jul 1, 2026
f784e71
added more order details registries & minor improvements on fleet/hei…
roncodes Jul 1, 2026
2c6cc68
script to fix rgba alpha normalization from percentage to decimal
roncodes Jul 1, 2026
02bc35a
Fix fleet hierarchy dropdown formatting
roncodes Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .stylelintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
rules: {
'selector-class-pattern': null,
'no-descending-specificity': null,
'alpha-value-notation': null,
'color-function-notation': null,
},
};
297 changes: 297 additions & 0 deletions addon/components/ai/create-order-preview.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
<div class="fleetbase-ai-response-region fleetbase-ai-create-order-preview" {{did-update this.updatePreview @preview}}>
<div class="fleetbase-ai-create-order-preview__header">
<div>
<div class="fleetbase-ai-action-title">{{this.preview.label}}</div>
<div class="fleetbase-ai-action-message">{{this.preview.message}}</div>
</div>
<span class="fleetbase-ai-action-status">{{if this.isCompleted "Completed" (if this.isCancelled "Cancelled" (if this.preview.ready "Ready" "Needs info"))}}</span>
</div>

{{#if @isApplying}}
<div class="fleetbase-ai-create-order-preview__applying">
<span class="fleetbase-ai-create-order-preview__magic-loader" aria-hidden="true">
<span></span>
<span></span>
<span></span>
</span>
<span>Creating Fleet-Ops order...</span>
</div>
{{else if this.isCompleted}}
<div class="fleetbase-ai-create-order-preview__completed">
<div class="fleetbase-ai-create-order-preview__completed-icon">
<FaIcon @icon="check" />
</div>
<div class="fleetbase-ai-create-order-preview__completed-copy">
<strong>{{this.completedMessage}}</strong>
<span>{{this.orderReference}}</span>
</div>
{{#if this.canOpenOrder}}
<Button @size="sm" @icon="arrow-up-right-from-square" @text="Open order" @onClick={{this.openOrder}} />
{{/if}}
</div>
{{else if this.isCancelled}}
<div class="fleetbase-ai-create-order-preview__cancelled">
<FaIcon @icon="circle-xmark" />
<span>{{this.cancelledMessage}}</span>
</div>
{{else if this.preview.error}}
<div class="fleetbase-ai-action-error">{{this.preview.error.message}}</div>
{{else}}
<Ai::RoutePreviewMap @payload={{this.payload}} @orderId={{this.orderPreviewId}} @status="created" />

<div class="fleetbase-ai-create-order-preview__fields">
<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Order type</span>
{{#if this.isEditingOrderType}}
<ModelSelect
@modelName="order-config"
@selectedModel={{this.draft.order_config_uuid}}
@placeholder="Select order type"
@triggerClass="fleetbase-ai-create-order-preview__inline-select"
@infiniteScroll={{false}}
@renderInPlace={{true}}
@onChange={{this.setOrderConfig}}
as |model|
>
{{or model.name model.key}}
</ModelSelect>
{{else}}
<strong>{{this.orderTypeLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingOrderType "xmark" "pen"}}
@helpText={{if this.isEditingOrderType "Close editor" "Edit order type"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingOrderType this.closeEditor (fn this.editField "orderType")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Schedule</span>
{{#if this.isEditingSchedule}}
<DateTimeInput
class="fleetbase-ai-create-order-preview__inline-datetime"
@value={{this.draft.scheduled_at}}
@minDate={{format-date-fns (now) "yyyy-MM-dd"}}
@minTime={{format-date-fns (now) "HH:mm"}}
@onUpdate={{this.setScheduledAt}}
/>
{{else}}
<strong>
{{#if this.draft.scheduled_at}}
{{format-date-fns this.draft.scheduled_at "yyyy-MM-dd HH:mm" fallback=this.scheduledAtLabel}}
{{else}}
{{this.scheduledAtLabel}}
{{/if}}
</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingSchedule "check" "pen"}}
@helpText={{if this.isEditingSchedule "Done" "Edit schedule"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingSchedule this.closeEditor (fn this.editField "schedule")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Pickup</span>
{{#if this.isEditingPickup}}
<ModelSelect
@modelName="place"
@selectedModel={{this.payload.pickup}}
@placeholder="Pickup address"
@triggerClass="fleetbase-ai-create-order-preview__inline-select"
@customSearchEndpoint="places/search"
@query={{hash geo=true}}
@infiniteScroll={{false}}
@renderInPlace={{true}}
@onChange={{fn this.setPayloadPlace "pickup"}}
as |place|
>
<div class="fleetbase-ai-create-order-preview__select-label">{{this.addressLabel place}}</div>
</ModelSelect>
{{else}}
<strong>{{this.pickupLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingPickup "xmark" "pen"}}
@helpText={{if this.isEditingPickup "Close editor" "Edit pickup"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingPickup this.closeEditor (fn this.editField "pickup")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Dropoff</span>
{{#if this.isEditingDropoff}}
<ModelSelect
@modelName="place"
@selectedModel={{this.payload.dropoff}}
@placeholder="Dropoff address"
@triggerClass="fleetbase-ai-create-order-preview__inline-select"
@customSearchEndpoint="places/search"
@query={{hash geo=true}}
@infiniteScroll={{false}}
@renderInPlace={{true}}
@onChange={{fn this.setPayloadPlace "dropoff"}}
as |place|
>
<div class="fleetbase-ai-create-order-preview__select-label">{{this.addressLabel place}}</div>
</ModelSelect>
{{else}}
<strong>{{this.dropoffLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingDropoff "xmark" "pen"}}
@helpText={{if this.isEditingDropoff "Close editor" "Edit dropoff"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingDropoff this.closeEditor (fn this.editField "dropoff")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Driver</span>
{{#if this.isEditingDriver}}
<ModelSelect
@modelName="driver"
@placeholder="Assign driver"
@triggerClass="fleetbase-ai-create-order-preview__inline-select"
@allowClear={{true}}
@infiniteScroll={{false}}
@renderInPlace={{true}}
@onChange={{this.setDriver}}
as |driver|
>
{{driver.name}}
</ModelSelect>
{{else}}
<strong>{{this.driverLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingDriver "xmark" "pen"}}
@helpText={{if this.isEditingDriver "Close editor" "Edit driver"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingDriver this.closeEditor (fn this.editField "driver")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Vehicle</span>
{{#if this.isEditingVehicle}}
<ModelSelect
@modelName="vehicle"
@placeholder="Assign vehicle"
@triggerClass="fleetbase-ai-create-order-preview__inline-select"
@allowClear={{true}}
@infiniteScroll={{false}}
@renderInPlace={{true}}
@onChange={{this.setVehicle}}
as |vehicle|
>
{{or vehicle.display_name vehicle.name vehicle.plate_number}}
</ModelSelect>
{{else}}
<strong>{{this.vehicleLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingVehicle "xmark" "pen"}}
@helpText={{if this.isEditingVehicle "Close editor" "Edit vehicle"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingVehicle this.closeEditor (fn this.editField "vehicle")}}
/>
</div>

<div class="fleetbase-ai-create-order-preview__field-row fleetbase-ai-create-order-preview__field-row--notes">
<div class="fleetbase-ai-create-order-preview__field-copy">
<span>Notes</span>
{{#if this.isEditingNotes}}
<Textarea
@value={{this.draft.notes}}
class="fleetbase-ai-create-order-preview__inline-textarea"
rows={{2}}
placeholder="Add order notes"
{{on "input" this.setNotes}}
/>
{{else}}
<strong>{{this.notesLabel}}</strong>
{{/if}}
</div>
<Button
@icon={{if this.isEditingNotes "check" "pen"}}
@helpText={{if this.isEditingNotes "Done" "Edit notes"}}
@wrapperClass="fleetbase-ai-create-order-preview__edit-wrapper"
class="fleetbase-ai-create-order-preview__edit-button"
@onClick={{if this.isEditingNotes this.closeEditor (fn this.editField "notes")}}
/>
</div>
</div>

<div class="fleetbase-ai-create-order-preview__toggles">
<div class="fleetbase-ai-create-order-preview__toggle-row">
<Toggle @isToggled={{this.draft.pod_required}} @onToggle={{this.setPodRequired}} @label="Require POD" />
{{#if this.draft.pod_required}}
{{#if this.isEditingPodMethod}}
<select class="fleetbase-ai-create-order-preview__inline-native-select" value={{this.draft.pod_method}} {{on "change" this.setPodMethodFromEvent}}>
{{#each this.podMethods as |method|}}
<option value={{method}} selected={{eq method this.draft.pod_method}}>{{this.titleize method}}</option>
{{/each}}
</select>
{{else}}
<button type="button" class="fleetbase-ai-create-order-preview__inline-pill" {{on "click" (fn this.editField "podMethod")}}>
{{this.podMethodLabel}}
<FaIcon @icon="pen" />
</button>
{{/if}}
{{/if}}
</div>
<div class="fleetbase-ai-create-order-preview__toggle-row">
<Toggle @isToggled={{this.draft.dispatched}} @onToggle={{this.setDispatched}} @label="Dispatch after create" />
</div>
</div>

{{#if this.hasMissingFields}}
<div class="fleetbase-ai-action-list">
<div class="fleetbase-ai-action-list-title">Required before apply</div>
<ul>
{{#each this.missingFields as |field|}}
<li>{{field}}</li>
{{/each}}
</ul>
</div>
{{/if}}

<div class="fleetbase-ai-create-order-preview__controls">
<Button
@type="primary"
@size="sm"
@icon="check"
@text="Create order"
@disabled={{this.isApplyDisabled}}
@isLoading={{@isApplying}}
@onClick={{this.apply}}
/>
<Button @size="sm" @icon="xmark" @text="Cancel" @disabled={{@isCancelling}} @onClick={{this.cancel}} />
{{#if this.refreshPreview.isRunning}}
<span class="fleetbase-ai-create-order-preview__refreshing">Updating preview...</span>
{{/if}}
</div>
{{/if}}
</div>
Loading
Loading