Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
4c768e2
feat(maintenance): complete maintenance module with maintenances, wor…
Mar 30, 2026
1b9b20e
fix missing translations
roncodes Mar 31, 2026
89c4cc9
feat(maintenance): restructure all four resource forms into organised…
Mar 31, 2026
02ed4a9
fix(maintenance): ContentPanel wrapperClass, work-order type options,…
Mar 31, 2026
6e41ea3
fix(maintenance): merge photo into Identification panel for equipment…
Mar 31, 2026
3cfbd2c
fix(maintenance): use label/value objects for asset type and performe…
Mar 31, 2026
6b93af8
fix(maintenance): add public_id migration, invoice-style cost line it…
Mar 31, 2026
2dfeec2
fix: replace per-field canSelectCurrency with single CurrencySelect
Mar 31, 2026
5a2391a
use correct placeholder image value for equipment and part
roncodes Mar 31, 2026
359e930
Merge branch 'feat/complete-maintenance-module' of github.com:fleetba…
roncodes Mar 31, 2026
673c1ed
feat(maintenance): add grid/table layout toggle for Equipment and Parts
Mar 31, 2026
a40fe1e
feat(maintenance): vehicle contextual actions + details maintenance tabs
Mar 31, 2026
4b7357d
feat(maintenance): scheduling engine — migration, model, observer, co…
Mar 31, 2026
a3ea1d2
feat(maintenance): frontend scheduling UI — schedules section, sideba…
Mar 31, 2026
2b483e6
fix(migration): shorten default_assignee composite index name to stay…
Mar 31, 2026
0a9395d
fix(schedules): replace Overlay with Layout::Resource::Panel for new/…
Mar 31, 2026
da887b4
fix(schedules): proper DateTimeInput, interval method selector, Model…
Mar 31, 2026
1b805cd
fix(migration): add public_id and interval_method columns to maintena…
Mar 31, 2026
9048fa3
fix(model): remove public_id from appends in MaintenanceSchedule — it…
Mar 31, 2026
a1ad10f
fix(controllers): replace non-existent table/cell/humanize with table…
Mar 31, 2026
2d61848
refactor(maintenance): fix 5 issues — rename service, getters, menuSe…
Mar 31, 2026
262e98c
fix(maintenance): add missing closing braces in maintenances and work…
Mar 31, 2026
606b6d6
several minor fixes w/ formatting and namespaces
roncodes Apr 1, 2026
dc76b99
fix: work order code/opened_at, cost breakdown in details, schedule W…
Apr 1, 2026
847363b
feat(maintenance): migrate forms and details to polymorphic relations…
Apr 1, 2026
eb27ff2
minor fixes
roncodes Apr 1, 2026
8a7daae
Merge branch 'feat/complete-maintenance-module' of github.com:fleetba…
roncodes Apr 1, 2026
bba2c54
complete merge
roncodes Apr 1, 2026
62db98f
fix(maintenance): remove console.fleet-ops prefix from routes and fix…
Apr 1, 2026
c2bb61a
feat(maintenance): add resource transformers and eager-load polymorph…
Apr 1, 2026
27e4f12
fix(maintenance): remove : array return type hint from resource trans…
Apr 1, 2026
2185751
fix(maintenance): add HasCustomFields trait to MaintenanceSchedule model
Apr 1, 2026
429a918
fix(maintenance): inject abstract type field into embedded polymorphi…
Apr 1, 2026
ccc7087
minor fixes for transitions
roncodes Apr 1, 2026
43433b4
fix(maintenance): correct action labels, remove formComponent anti-pa…
Apr 1, 2026
5a815e0
make sure correct default currency set for part & equipment resources
roncodes Apr 1, 2026
81f6d4c
Merge branch 'feat/complete-maintenance-module' of github.com:fleetba…
roncodes Apr 1, 2026
7b7160c
fix: wire MoneyInput @onChange bindings and fix cents handling across…
roncodes Apr 1, 2026
aeda17f
feat: add import capability for all maintenance resources + Send Work…
roncodes Apr 1, 2026
b242b10
few minor patches
roncodes Apr 1, 2026
54b46ef
Merge branch 'feat/complete-maintenance-module' of github.com:fleetba…
roncodes Apr 1, 2026
873dca6
fix: cost-panel in-memory line items and numbersOnly monetary getters
roncodes Apr 1, 2026
0d669c3
feat: rich Send Work Order confirmation modal with vendor and subject…
roncodes Apr 1, 2026
0ffa07e
fix: add app re-export for modals/send-work-order component
roncodes Apr 1, 2026
d3f62e4
fix: remove slug from WorkOrder fillable and add code auto-generation…
roncodes Apr 1, 2026
c113dfc
fix cost panel item format-currency bit
roncodes Apr 1, 2026
4e72e62
fix: resolve column mismatch errors on equipment, parts, work_orders …
roncodes Apr 1, 2026
047def9
fix: properly handle photo_uuid and public_id column issues
roncodes Apr 1, 2026
fcba12e
feat(maintenance): improve all resource detail components with proper…
roncodes Apr 1, 2026
43dc608
fix: normalise line_items unit_cost to cents and eager-load maintaina…
roncodes Apr 1, 2026
bc5a228
several small fixes
roncodes Apr 1, 2026
d9cccc0
fix: pass explicit uuid column names to all morphTo() calls
roncodes Apr 1, 2026
b4735d2
fix: add public_id to equipments table via new idempotent migration
roncodes Apr 1, 2026
eb91528
fix: add missing status, currency, public_id columns to parts table
roncodes Apr 1, 2026
4e65033
fix(resources): use bare class_basename slug in polymorphic type inje…
roncodes Apr 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
49 changes: 49 additions & 0 deletions addon/components/equipment/card.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<Layout::Resource::Card ...attributes as |Card|>
<Card.header class="{{@headerClass}} truncate">
<div class="font-semibold truncate">{{or @resource.name @resource.public_id}}</div>
<div class="text-gray-300 dark:text-gray-500 text-sm truncate">{{or @resource.serial_number @resource.code @resource.public_id}}</div>
{{#if (has-block "header")}}
{{yield to="header"}}
{{/if}}
</Card.header>
<Card.body class={{@bodyClass}}>
<Image src={{@resource.photo_url}} @fallbackSrc={{config "defaultValues.equipmentImage"}} class="card-img-lg" />
<div class="mt-2 space-y-1 text-xs text-gray-500 dark:text-gray-400">
{{#if @resource.type}}
<div class="flex items-center space-x-1">
<FaIcon @icon="tag" @size="xs" class="text-gray-400" />
<span>{{humanize @resource.type}}</span>
</div>
{{/if}}
{{#if @resource.status}}
<div class="flex items-center space-x-1">
<FaIcon @icon="circle" @size="xs" class="text-gray-400" />
<span>{{humanize @resource.status}}</span>
</div>
{{/if}}
{{#if @resource.year}}
<div class="flex items-center space-x-1">
<FaIcon @icon="calendar" @size="xs" class="text-gray-400" />
<span>{{@resource.year}}</span>
</div>
{{/if}}
</div>
{{#if (has-block "body")}}
{{yield to="body"}}
{{/if}}
</Card.body>
<Card.footer class={{@footerClass}}>
<div class="flex flex-row items-center space-x-1">
<Button @icon="eye" @size="xs" @onClick={{fn this.equipmentActions.transition.view @resource}} />
<Button @icon="pencil" @size="xs" @onClick={{fn this.equipmentActions.transition.edit @resource}} />
<Button @icon="trash" @size="xs" @type="danger" @onClick={{fn this.equipmentActions.delete @resource}} />
</div>
{{#if (has-block "footer")}}
{{yield to="footer"}}
{{/if}}
<div class="mt-1">
<div class="text-gray-300 dark:text-gray-500 text-xs">Last Modified: {{@resource.updatedAt}}</div>
</div>
</Card.footer>
</Layout::Resource::Card>
{{yield}}
6 changes: 6 additions & 0 deletions addon/components/equipment/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';

export default class EquipmentCardComponent extends Component {
@service equipmentActions;
}
125 changes: 82 additions & 43 deletions addon/components/equipment/details.hbs
Original file line number Diff line number Diff line change
@@ -1,63 +1,75 @@
<div class="details-wrapper" ...attributes>
<ContentPanel @title="Details" @open={{true}} @wrapperClass="bordered-top">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
<div class="next-content-panel-wrapper" ...attributes>

{{! ===== OVERVIEW ===== }}
<ContentPanel @title="Overview" @open={{true}} @wrapperClass="bordered-top">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">

{{! — Photo — }}
{{#if (or @resource.photo_url (config "defaultValues.equipmentImage"))}}
<div class="col-span-2 flex items-center gap-3 pb-2 border-b border-gray-100 dark:border-gray-700 mb-1">
<div class="border border-dashed border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-600 rounded-lg flex items-center justify-center w-16 h-16 flex-shrink-0">
<Image
alt={{@resource.name}}
src={{or @resource.photo_url (config "defaultValues.equipmentImage")}}
@fallbackSrc={{config "defaultValues.equipmentImage"}}
class="w-12 h-12 object-contain"
/>
</div>
<div>
<p class="font-semibold text-sm text-gray-800 dark:text-gray-100">{{n-a @resource.name}}</p>
<p class="text-[11px] text-gray-400 dark:text-gray-500 font-mono">{{n-a @resource.public_id}}</p>
</div>
</div>
{{/if}}

{{! — Identity & Classification — }}
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-1">
Identity & Classification
</div>
<div class="field-info-container">
<div class="field-name">Name</div>
<div class="field-value">{{n-a @resource.name}}</div>
<div class="field-name">ID</div>
<ClickToCopy @value={{@resource.public_id}} class="field-value font-mono">{{n-a @resource.public_id}}</ClickToCopy>
</div>

<div class="field-info-container">
<div class="field-name">Code</div>
<div class="field-value">{{n-a @resource.code}}</div>
<ClickToCopy @value={{@resource.code}} class="field-value font-mono">{{n-a @resource.code}}</ClickToCopy>
</div>
<div class="field-info-container">
<div class="field-name">Name</div>
<div class="field-value">{{n-a @resource.name}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Type</div>
<div class="field-value">{{smart-humanize @resource.type}}</div>
<div class="field-value">{{n-a (smart-humanize @resource.type)}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Status</div>
<div class="field-value">
<Badge @status={{@resource.status}}>{{smart-humanize @resource.status}}</Badge>
</div>
</div>

<div class="field-info-container">
<div class="field-name">Serial Number</div>
<div class="field-value">{{n-a @resource.serial_number}}</div>
<div class="field-value font-mono">{{n-a @resource.serial_number}}</div>
</div>

{{! — Make & Model — }}
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
Make & Model
</div>
<div class="field-info-container">
<div class="field-name">Manufacturer</div>
<div class="field-value">{{n-a @resource.manufacturer}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Model</div>
<div class="field-value">{{n-a @resource.model}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Purchased At</div>
<div class="field-value">{{format-date @resource.purchased_at}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Purchase Price</div>
<div class="field-value">{{format-currency @resource.purchase_price}}</div>
{{! — Assignment — }}
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
Assignment
</div>

<div class="field-info-container">
<div class="field-name">Warranty</div>
<div class="field-value">{{n-a @resource.warranty_name}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Equipped To</div>
<div class="field-value">{{n-a @resource.equipped_to_name}}</div>
</div>

<div class="field-info-container">
<div class="field-name">Equipped Status</div>
<div class="field-value">
Expand All @@ -68,28 +80,55 @@
{{/if}}
</div>
</div>
{{#if @resource.is_equipped}}
<div class="field-info-container">
<div class="field-name">Equipped To</div>
<div class="field-value">{{n-a @resource.equipped_to_name}}</div>
</div>
{{/if}}
</div>
</ContentPanel>

{{! ===== FINANCIALS ===== }}
<ContentPanel @title="Financials" @open={{true}} @wrapperClass="bordered-top">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">
<div class="field-info-container">
<div class="field-name">Purchase Price</div>
<div class="field-value">{{format-currency @resource.purchase_price @resource.currency}}</div>
</div>
<div class="field-info-container">
<div class="field-name">Purchased At</div>
<div class="field-value">{{n-a (format-date-fns @resource.purchased_at "dd MMM yyyy")}}</div>
</div>
<div class="field-info-container">
<div class="field-name">Age</div>
<div class="field-value">{{n-a @resource.age_in_days}} days</div>
</div>

<div class="field-info-container">
<div class="field-name">Depreciated Value</div>
<div class="field-value">{{format-currency @resource.depreciated_value}}</div>
<div class="field-value">{{format-currency @resource.depreciated_value @resource.currency}}</div>
</div>
<div class="field-info-container">
<div class="field-name">Currency</div>
<div class="field-value">{{n-a @resource.currency}}</div>
</div>
</div>
</ContentPanel>

<CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />

<ContentPanel @title="Photo" @open={{true}} @wrapperClass="bordered-top">
<div class="flex px-1">
<div class="border border-dashed border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-600 rounded-lg flex items-center justify-center">
<div class="flex items-center justify-center h-20 w-24">
<Image alt={{@resource.name}} src={{or @resource.photo_url (config "defaultValues.equipmentImage")}} @fallbackSrc={{config "defaultValues.equipmentImage"}} class="w-12 h-12" />
{{! ===== WARRANTY ===== }}
{{#if @resource.warranty_name}}
<ContentPanel @title="Warranty" @open={{true}} @wrapperClass="bordered-top">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">
<div class="field-info-container">
<div class="field-name">Warranty</div>
<div class="field-value">{{n-a @resource.warranty_name}}</div>
</div>
</div>
</div>
</ContentPanel>
</ContentPanel>
{{/if}}

{{! ===== CUSTOM FIELDS ===== }}
<CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />

<Spacer @height="200px" />
</div>
Loading
Loading