@salesforce/ui-bundle-template-app-react-sample-b2e 1.117.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +52 -0
  3. package/dist/.forceignore +15 -0
  4. package/dist/.husky/pre-commit +4 -0
  5. package/dist/.prettierignore +11 -0
  6. package/dist/.prettierrc +17 -0
  7. package/dist/AGENT.md +193 -0
  8. package/dist/CHANGELOG.md +2128 -0
  9. package/dist/README.md +104 -0
  10. package/dist/config/project-scratch-def.json +13 -0
  11. package/dist/eslint.config.js +7 -0
  12. package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler.cls +69 -0
  13. package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler.cls-meta.xml +5 -0
  14. package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler_Test.cls +308 -0
  15. package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler_Test.cls-meta.xml +5 -0
  16. package/dist/force-app/main/default/classes/TenantTriggerHandler.cls +77 -0
  17. package/dist/force-app/main/default/classes/TenantTriggerHandler.cls-meta.xml +5 -0
  18. package/dist/force-app/main/default/classes/TenantTriggerHandler_Test.cls +100 -0
  19. package/dist/force-app/main/default/classes/TenantTriggerHandler_Test.cls-meta.xml +5 -0
  20. package/dist/force-app/main/default/cspTrustedSites/GitHub_Avatars.cspTrustedSite-meta.xml +15 -0
  21. package/dist/force-app/main/default/cspTrustedSites/Google_Fonts.cspTrustedSite-meta.xml +15 -0
  22. package/dist/force-app/main/default/cspTrustedSites/Google_Fonts_Static.cspTrustedSite-meta.xml +15 -0
  23. package/dist/force-app/main/default/cspTrustedSites/OpenStreetMap_Nominatim.cspTrustedSite-meta.xml +15 -0
  24. package/dist/force-app/main/default/cspTrustedSites/OpenStreetMap_Tiles.cspTrustedSite-meta.xml +15 -0
  25. package/dist/force-app/main/default/cspTrustedSites/Open_Meteo_API.cspTrustedSite-meta.xml +15 -0
  26. package/dist/force-app/main/default/cspTrustedSites/Pexels_Images.cspTrustedSite-meta.xml +15 -0
  27. package/dist/force-app/main/default/cspTrustedSites/Pexels_Videos.cspTrustedSite-meta.xml +15 -0
  28. package/dist/force-app/main/default/cspTrustedSites/Unsplash_Images.cspTrustedSite-meta.xml +15 -0
  29. package/dist/force-app/main/default/data/Agent__c.json +79 -0
  30. package/dist/force-app/main/default/data/Application__c.json +124 -0
  31. package/dist/force-app/main/default/data/Contact.json +44 -0
  32. package/dist/force-app/main/default/data/KPI_Snapshot__c.json +160 -0
  33. package/dist/force-app/main/default/data/Lease__c.json +9442 -0
  34. package/dist/force-app/main/default/data/Maintenance_Request__c.json +514 -0
  35. package/dist/force-app/main/default/data/Maintenance_Worker__c.json +304 -0
  36. package/dist/force-app/main/default/data/Notification__c.json +214 -0
  37. package/dist/force-app/main/default/data/Payment__c.json +1024 -0
  38. package/dist/force-app/main/default/data/Property_Cost__c.json +484 -0
  39. package/dist/force-app/main/default/data/Property_Feature__c.json +169 -0
  40. package/dist/force-app/main/default/data/Property_Image__c.json +148 -0
  41. package/dist/force-app/main/default/data/Property_Listing__c.json +130 -0
  42. package/dist/force-app/main/default/data/Property_Management_Company__c.json +70 -0
  43. package/dist/force-app/main/default/data/Property_Owner__c.json +184 -0
  44. package/dist/force-app/main/default/data/Property_Sale__c.json +246 -0
  45. package/dist/force-app/main/default/data/Property__c.json +704 -0
  46. package/dist/force-app/main/default/data/Tenant__c.json +184 -0
  47. package/dist/force-app/main/default/data/data-plan.json +110 -0
  48. package/dist/force-app/main/default/data/prepare-import-unique-fields.js +85 -0
  49. package/dist/force-app/main/default/layouts/Application__c-Application Layout.layout-meta.xml +58 -0
  50. package/dist/force-app/main/default/layouts/KPI_Snapshot__c-KPI Snapshot Layout.layout-meta.xml +87 -0
  51. package/dist/force-app/main/default/layouts/Lease__c-Lease Layout.layout-meta.xml +83 -0
  52. package/dist/force-app/main/default/layouts/Maintenance_Request__c-Maintenance Request Layout.layout-meta.xml +89 -0
  53. package/dist/force-app/main/default/layouts/Maintenance_Worker__c-Maintenance Worker Layout.layout-meta.xml +66 -0
  54. package/dist/force-app/main/default/layouts/Payment__c-Payment Layout.layout-meta.xml +88 -0
  55. package/dist/force-app/main/default/layouts/Property_Cost__c-Property Cost Layout.layout-meta.xml +88 -0
  56. package/dist/force-app/main/default/layouts/Property_Feature__c-Property Feature Layout.layout-meta.xml +80 -0
  57. package/dist/force-app/main/default/layouts/Property_Image__c-Property Image Layout.layout-meta.xml +75 -0
  58. package/dist/force-app/main/default/layouts/Property_Listing__c-Property Listing Layout.layout-meta.xml +92 -0
  59. package/dist/force-app/main/default/layouts/Property_Management_Company__c-Property Management Company Layout.layout-meta.xml +75 -0
  60. package/dist/force-app/main/default/layouts/Property_Owner__c-Property Owner Layout.layout-meta.xml +67 -0
  61. package/dist/force-app/main/default/layouts/Property_Sale__c-Property Sale Layout.layout-meta.xml +87 -0
  62. package/dist/force-app/main/default/layouts/Property__c-Property Layout.layout-meta.xml +130 -0
  63. package/dist/force-app/main/default/layouts/Tenant__c-Tenant Layout.layout-meta.xml +58 -0
  64. package/dist/force-app/main/default/objects/Agent__c/Agent__c.object-meta.xml +66 -0
  65. package/dist/force-app/main/default/objects/Agent__c/fields/Agent_Type__c.field-meta.xml +37 -0
  66. package/dist/force-app/main/default/objects/Agent__c/fields/Availability__c.field-meta.xml +37 -0
  67. package/dist/force-app/main/default/objects/Agent__c/fields/Emergency_Alt__c.field-meta.xml +11 -0
  68. package/dist/force-app/main/default/objects/Agent__c/fields/Language__c.field-meta.xml +42 -0
  69. package/dist/force-app/main/default/objects/Agent__c/fields/License_Expiry__c.field-meta.xml +11 -0
  70. package/dist/force-app/main/default/objects/Agent__c/fields/License_Number__c.field-meta.xml +14 -0
  71. package/dist/force-app/main/default/objects/Agent__c/fields/Office_Location__c.field-meta.xml +42 -0
  72. package/dist/force-app/main/default/objects/Agent__c/fields/Territory__c.field-meta.xml +42 -0
  73. package/dist/force-app/main/default/objects/Application__c/Application__c.object-meta.xml +67 -0
  74. package/dist/force-app/main/default/objects/Application__c/fields/Employment__c.field-meta.xml +10 -0
  75. package/dist/force-app/main/default/objects/Application__c/fields/Property__c.field-meta.xml +15 -0
  76. package/dist/force-app/main/default/objects/Application__c/fields/References__c.field-meta.xml +10 -0
  77. package/dist/force-app/main/default/objects/Application__c/fields/Start_Date__c.field-meta.xml +9 -0
  78. package/dist/force-app/main/default/objects/Application__c/fields/Status__c.field-meta.xml +47 -0
  79. package/dist/force-app/main/default/objects/Application__c/fields/User__c.field-meta.xml +15 -0
  80. package/dist/force-app/main/default/objects/KPI_Snapshot__c/KPI_Snapshot__c.object-meta.xml +65 -0
  81. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Previous_Month_Sales__c.field-meta.xml +12 -0
  82. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Sales_MoM_Change__c.field-meta.xml +18 -0
  83. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Snapshot_Date__c.field-meta.xml +10 -0
  84. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Properties__c.field-meta.xml +13 -0
  85. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Sales_Amount__c.field-meta.xml +12 -0
  86. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Sales_Count__c.field-meta.xml +13 -0
  87. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Units_Available__c.field-meta.xml +13 -0
  88. package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Units_Occupied__c.field-meta.xml +13 -0
  89. package/dist/force-app/main/default/objects/Lease__c/Lease__c.object-meta.xml +67 -0
  90. package/dist/force-app/main/default/objects/Lease__c/fields/End_Date__c.field-meta.xml +10 -0
  91. package/dist/force-app/main/default/objects/Lease__c/fields/Lease_Status__c.field-meta.xml +36 -0
  92. package/dist/force-app/main/default/objects/Lease__c/fields/Monthly_Rent__c.field-meta.xml +12 -0
  93. package/dist/force-app/main/default/objects/Lease__c/fields/Property__c.field-meta.xml +15 -0
  94. package/dist/force-app/main/default/objects/Lease__c/fields/Security_Deposit__c.field-meta.xml +12 -0
  95. package/dist/force-app/main/default/objects/Lease__c/fields/Start_Date__c.field-meta.xml +10 -0
  96. package/dist/force-app/main/default/objects/Lease__c/fields/Tenant__c.field-meta.xml +14 -0
  97. package/dist/force-app/main/default/objects/Lease__c/validationRules/End_Date_After_Start_Date.validationRule-meta.xml +10 -0
  98. package/dist/force-app/main/default/objects/Maintenance_Request__c/Maintenance_Request__c.object-meta.xml +73 -0
  99. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Actual_Cost__c.field-meta.xml +13 -0
  100. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Assigned_Worker__c.field-meta.xml +15 -0
  101. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Completed__c.field-meta.xml +11 -0
  102. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Description__c.field-meta.xml +12 -0
  103. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Est_Cost__c.field-meta.xml +13 -0
  104. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Priority__c.field-meta.xml +32 -0
  105. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Property__c.field-meta.xml +15 -0
  106. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Scheduled__c.field-meta.xml +11 -0
  107. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Status__c.field-meta.xml +42 -0
  108. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Tenant_Home__c.field-meta.xml +11 -0
  109. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Type__c.field-meta.xml +62 -0
  110. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/User__c.field-meta.xml +15 -0
  111. package/dist/force-app/main/default/objects/Maintenance_Worker__c/Maintenance_Worker__c.object-meta.xml +71 -0
  112. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Certifications__c.field-meta.xml +12 -0
  113. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Employment_Type__c.field-meta.xml +32 -0
  114. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Hourly_Rate__c.field-meta.xml +13 -0
  115. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/IsActive__c.field-meta.xml +11 -0
  116. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Location__c.field-meta.xml +13 -0
  117. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Phone__c.field-meta.xml +11 -0
  118. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Rating__c.field-meta.xml +14 -0
  119. package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Type__c.field-meta.xml +57 -0
  120. package/dist/force-app/main/default/objects/Notification__c/Notification__c.object-meta.xml +67 -0
  121. package/dist/force-app/main/default/objects/Notification__c/fields/Is_Read__c.field-meta.xml +10 -0
  122. package/dist/force-app/main/default/objects/Notification__c/fields/Message__c.field-meta.xml +11 -0
  123. package/dist/force-app/main/default/objects/Notification__c/fields/Priority__c.field-meta.xml +36 -0
  124. package/dist/force-app/main/default/objects/Notification__c/fields/Related_Object_Type__c.field-meta.xml +12 -0
  125. package/dist/force-app/main/default/objects/Notification__c/fields/Related_Record_Id__c.field-meta.xml +12 -0
  126. package/dist/force-app/main/default/objects/Notification__c/fields/Title__c.field-meta.xml +12 -0
  127. package/dist/force-app/main/default/objects/Notification__c/fields/Type__c.field-meta.xml +36 -0
  128. package/dist/force-app/main/default/objects/Notification__c/fields/User__c.field-meta.xml +14 -0
  129. package/dist/force-app/main/default/objects/Payment__c/Payment__c.object-meta.xml +67 -0
  130. package/dist/force-app/main/default/objects/Payment__c/fields/Amount__c.field-meta.xml +12 -0
  131. package/dist/force-app/main/default/objects/Payment__c/fields/Lease__c.field-meta.xml +15 -0
  132. package/dist/force-app/main/default/objects/Payment__c/fields/Notes__c.field-meta.xml +11 -0
  133. package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Date__c.field-meta.xml +10 -0
  134. package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Method__c.field-meta.xml +41 -0
  135. package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Status__c.field-meta.xml +36 -0
  136. package/dist/force-app/main/default/objects/Property_Cost__c/Property_Cost__c.object-meta.xml +67 -0
  137. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Amount__c.field-meta.xml +12 -0
  138. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Category__c.field-meta.xml +56 -0
  139. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Date__c.field-meta.xml +11 -0
  140. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Description__c.field-meta.xml +12 -0
  141. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Property__c.field-meta.xml +15 -0
  142. package/dist/force-app/main/default/objects/Property_Cost__c/fields/Vendor__c.field-meta.xml +12 -0
  143. package/dist/force-app/main/default/objects/Property_Cost__c/validationRules/Cost_Amount_Limit.validationRule-meta.xml +10 -0
  144. package/dist/force-app/main/default/objects/Property_Feature__c/Property_Feature__c.object-meta.xml +65 -0
  145. package/dist/force-app/main/default/objects/Property_Feature__c/fields/Description__c.field-meta.xml +11 -0
  146. package/dist/force-app/main/default/objects/Property_Feature__c/fields/Display_on_Listing__c.field-meta.xml +10 -0
  147. package/dist/force-app/main/default/objects/Property_Feature__c/fields/Feature_Category__c.field-meta.xml +51 -0
  148. package/dist/force-app/main/default/objects/Property_Feature__c/fields/Property__c.field-meta.xml +15 -0
  149. package/dist/force-app/main/default/objects/Property_Image__c/Property_Image__c.object-meta.xml +65 -0
  150. package/dist/force-app/main/default/objects/Property_Image__c/fields/Alt_Text__c.field-meta.xml +12 -0
  151. package/dist/force-app/main/default/objects/Property_Image__c/fields/Display_Order__c.field-meta.xml +13 -0
  152. package/dist/force-app/main/default/objects/Property_Image__c/fields/Image_Type__c.field-meta.xml +41 -0
  153. package/dist/force-app/main/default/objects/Property_Image__c/fields/Image_URL__c.field-meta.xml +10 -0
  154. package/dist/force-app/main/default/objects/Property_Image__c/fields/Property__c.field-meta.xml +15 -0
  155. package/dist/force-app/main/default/objects/Property_Listing__c/Property_Listing__c.object-meta.xml +65 -0
  156. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Display_Order__c.field-meta.xml +13 -0
  157. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Featured__c.field-meta.xml +10 -0
  158. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Listing_Price__c.field-meta.xml +12 -0
  159. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Listing_Status__c.field-meta.xml +41 -0
  160. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Marketing_Description__c.field-meta.xml +11 -0
  161. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Property__c.field-meta.xml +15 -0
  162. package/dist/force-app/main/default/objects/Property_Listing__c/fields/Short_Description__c.field-meta.xml +12 -0
  163. package/dist/force-app/main/default/objects/Property_Management_Company__c/Property_Management_Company__c.object-meta.xml +65 -0
  164. package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Active__c.field-meta.xml +10 -0
  165. package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Company_Code__c.field-meta.xml +13 -0
  166. package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Email__c.field-meta.xml +10 -0
  167. package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Phone__c.field-meta.xml +10 -0
  168. package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Primary_Contact__c.field-meta.xml +14 -0
  169. package/dist/force-app/main/default/objects/Property_Owner__c/Property_Owner__c.object-meta.xml +65 -0
  170. package/dist/force-app/main/default/objects/Property_Owner__c/fields/Address__c.field-meta.xml +10 -0
  171. package/dist/force-app/main/default/objects/Property_Owner__c/fields/Email__c.field-meta.xml +11 -0
  172. package/dist/force-app/main/default/objects/Property_Owner__c/fields/Phone__c.field-meta.xml +10 -0
  173. package/dist/force-app/main/default/objects/Property_Sale__c/Property_Sale__c.object-meta.xml +67 -0
  174. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Buyer_Tenant__c.field-meta.xml +13 -0
  175. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Payment_Method__c.field-meta.xml +41 -0
  176. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Property__c.field-meta.xml +15 -0
  177. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Reference_Number__c.field-meta.xml +12 -0
  178. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Amount__c.field-meta.xml +12 -0
  179. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Date__c.field-meta.xml +10 -0
  180. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Status__c.field-meta.xml +36 -0
  181. package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Type__c.field-meta.xml +51 -0
  182. package/dist/force-app/main/default/objects/Property__c/Property__c.object-meta.xml +71 -0
  183. package/dist/force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml +13 -0
  184. package/dist/force-app/main/default/objects/Property__c/fields/Agent__c.field-meta.xml +15 -0
  185. package/dist/force-app/main/default/objects/Property__c/fields/Available_Date__c.field-meta.xml +11 -0
  186. package/dist/force-app/main/default/objects/Property__c/fields/Bathrooms__c.field-meta.xml +14 -0
  187. package/dist/force-app/main/default/objects/Property__c/fields/Bedrooms__c.field-meta.xml +14 -0
  188. package/dist/force-app/main/default/objects/Property__c/fields/Coordinates__c.field-meta.xml +12 -0
  189. package/dist/force-app/main/default/objects/Property__c/fields/Deposit__c.field-meta.xml +13 -0
  190. package/dist/force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml +12 -0
  191. package/dist/force-app/main/default/objects/Property__c/fields/Features__c.field-meta.xml +38 -0
  192. package/dist/force-app/main/default/objects/Property__c/fields/Hero_Image__c.field-meta.xml +11 -0
  193. package/dist/force-app/main/default/objects/Property__c/fields/Lease_Term__c.field-meta.xml +14 -0
  194. package/dist/force-app/main/default/objects/Property__c/fields/Monthly_Rent__c.field-meta.xml +13 -0
  195. package/dist/force-app/main/default/objects/Property__c/fields/Parking__c.field-meta.xml +14 -0
  196. package/dist/force-app/main/default/objects/Property__c/fields/Pet_Friendly__c.field-meta.xml +11 -0
  197. package/dist/force-app/main/default/objects/Property__c/fields/Sq_Ft__c.field-meta.xml +14 -0
  198. package/dist/force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml +37 -0
  199. package/dist/force-app/main/default/objects/Property__c/fields/Tour_URL__c.field-meta.xml +11 -0
  200. package/dist/force-app/main/default/objects/Property__c/fields/Type__c.field-meta.xml +37 -0
  201. package/dist/force-app/main/default/objects/Property__c/fields/Utilities__c.field-meta.xml +38 -0
  202. package/dist/force-app/main/default/objects/Property__c/fields/Year_Built__c.field-meta.xml +14 -0
  203. package/dist/force-app/main/default/objects/Tenant__c/Tenant__c.object-meta.xml +67 -0
  204. package/dist/force-app/main/default/objects/Tenant__c/fields/End_Date__c.field-meta.xml +11 -0
  205. package/dist/force-app/main/default/objects/Tenant__c/fields/Property__c.field-meta.xml +15 -0
  206. package/dist/force-app/main/default/objects/Tenant__c/fields/Start_Date__c.field-meta.xml +11 -0
  207. package/dist/force-app/main/default/objects/Tenant__c/fields/Status__c.field-meta.xml +37 -0
  208. package/dist/force-app/main/default/objects/Tenant__c/fields/User_Status__c.field-meta.xml +42 -0
  209. package/dist/force-app/main/default/objects/Tenant__c/fields/User__c.field-meta.xml +15 -0
  210. package/dist/force-app/main/default/permissionsets/Property_Management_Access.permissionset-meta.xml +633 -0
  211. package/dist/force-app/main/default/permissionsets/Tenant_Maintenance_Access.permissionset-meta.xml +137 -0
  212. package/dist/force-app/main/default/triggers/MaintenanceRequestTrigger.trigger +5 -0
  213. package/dist/force-app/main/default/triggers/MaintenanceRequestTrigger.trigger-meta.xml +5 -0
  214. package/dist/force-app/main/default/triggers/TenantTrigger.trigger +8 -0
  215. package/dist/force-app/main/default/triggers/TenantTrigger.trigger-meta.xml +5 -0
  216. package/dist/force-app/main/default/uiBundles/propertymanagementapp/.forceignore +15 -0
  217. package/dist/force-app/main/default/uiBundles/propertymanagementapp/.graphqlrc.yml +2 -0
  218. package/dist/force-app/main/default/uiBundles/propertymanagementapp/.prettierignore +9 -0
  219. package/dist/force-app/main/default/uiBundles/propertymanagementapp/.prettierrc +11 -0
  220. package/dist/force-app/main/default/uiBundles/propertymanagementapp/CHANGELOG.md +10 -0
  221. package/dist/force-app/main/default/uiBundles/propertymanagementapp/README.md +35 -0
  222. package/dist/force-app/main/default/uiBundles/propertymanagementapp/codegen.yml +95 -0
  223. package/dist/force-app/main/default/uiBundles/propertymanagementapp/components.json +18 -0
  224. package/dist/force-app/main/default/uiBundles/propertymanagementapp/e2e/app.spec.ts +17 -0
  225. package/dist/force-app/main/default/uiBundles/propertymanagementapp/eslint.config.js +169 -0
  226. package/dist/force-app/main/default/uiBundles/propertymanagementapp/index.html +12 -0
  227. package/dist/force-app/main/default/uiBundles/propertymanagementapp/package.json +70 -0
  228. package/dist/force-app/main/default/uiBundles/propertymanagementapp/playwright.config.ts +24 -0
  229. package/dist/force-app/main/default/uiBundles/propertymanagementapp/propertymanagementapp.uibundle-meta.xml +7 -0
  230. package/dist/force-app/main/default/uiBundles/propertymanagementapp/scripts/get-graphql-schema.mjs +68 -0
  231. package/dist/force-app/main/default/uiBundles/propertymanagementapp/scripts/rewrite-e2e-assets.mjs +23 -0
  232. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/applicationSearchService.ts +46 -0
  233. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/applications.ts +122 -0
  234. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/applicationForApproval.graphql +22 -0
  235. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/distinctApplicationStatus.graphql +19 -0
  236. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/existingTenant.graphql +16 -0
  237. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/getApplications.graphql +44 -0
  238. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/searchApplications.graphql +65 -0
  239. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/updateApplicationStatus.graphql +13 -0
  240. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/userByContact.graphql +13 -0
  241. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/dashboard.ts +108 -0
  242. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getDashboardMetrics.graphql +39 -0
  243. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getOpenApplications.graphql +36 -0
  244. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getUserInfo.graphql +16 -0
  245. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/graphql-operations-types.ts +16420 -0
  246. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/graphqlClient.ts +25 -0
  247. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/maintenanceRequestSearchService.ts +66 -0
  248. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/maintenanceRequests.ts +75 -0
  249. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestPriority.graphql +19 -0
  250. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestStatus.graphql +19 -0
  251. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestType.graphql +19 -0
  252. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/getAllMaintenanceRequests.graphql +71 -0
  253. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/getMaintenanceRequests.graphql +41 -0
  254. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/searchMaintenanceRequests.graphql +82 -0
  255. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/updateMaintenanceStatus.graphql +13 -0
  256. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/maintenanceWorkerSearchService.ts +46 -0
  257. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/query/distinctMaintenanceWorkerEmploymentType.graphql +19 -0
  258. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/query/searchMaintenanceWorkers.graphql +64 -0
  259. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/properties.ts +43 -0
  260. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/propertySearchService.ts +56 -0
  261. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/distinctPropertyStatus.graphql +19 -0
  262. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/distinctPropertyType.graphql +19 -0
  263. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/getProperties.graphql +77 -0
  264. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/searchProperties.graphql +105 -0
  265. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/app.tsx +17 -0
  266. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/appLayout.tsx +32 -0
  267. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/appliances.svg +13 -0
  268. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/book.svg +3 -0
  269. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/copy.svg +4 -0
  270. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/dashboard.svg +4 -0
  271. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/downgraph.svg +3 -0
  272. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/electrical.svg +41 -0
  273. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/files.svg +7 -0
  274. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/hvac.svg +79 -0
  275. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/maintenance-worker.svg +8 -0
  276. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/maintenance.svg +4 -0
  277. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/pest.svg +5 -0
  278. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/plumbing.svg +7 -0
  279. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/properties.svg +14 -0
  280. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/rocket.svg +3 -0
  281. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/star.svg +3 -0
  282. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/support.svg +6 -0
  283. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/upgraph.svg +3 -0
  284. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/users.svg +8 -0
  285. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/zen-logo.svg +5 -0
  286. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-1.png +0 -0
  287. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-2.png +0 -0
  288. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-3.png +0 -0
  289. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/vibe-codey.svg +194 -0
  290. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/AgentforceConversationClient.tsx +168 -0
  291. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/alerts/status-alert.tsx +49 -0
  292. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/applications/ApplicationDetailsModal.tsx +142 -0
  293. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/GlobalSearchBar.tsx +101 -0
  294. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/IssuesDonutChart.tsx +122 -0
  295. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/MaintenanceTable.tsx +129 -0
  296. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/StatCard.tsx +73 -0
  297. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/FilterRow.tsx +23 -0
  298. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/PageContainer.tsx +13 -0
  299. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/PageHeader.tsx +17 -0
  300. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/TopBar.tsx +55 -0
  301. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/VerticalNav.tsx +75 -0
  302. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layouts/card-layout.tsx +29 -0
  303. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceRequests/MaintenanceDetailsModal.tsx +193 -0
  304. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceRequests/MaintenanceRequestCard.tsx +80 -0
  305. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceWorkers/WorkerDetailsModal.tsx +66 -0
  306. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/properties/PropertyCard.tsx +61 -0
  307. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/properties/PropertyDetailsModal.tsx +263 -0
  308. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/shared/ObjectSearchErrorState.tsx +45 -0
  309. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/shared/UserAvatar.tsx +35 -0
  310. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/alert.tsx +76 -0
  311. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/badge.tsx +48 -0
  312. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/breadcrumb.tsx +109 -0
  313. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/button.tsx +67 -0
  314. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/calendar.tsx +232 -0
  315. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/card.tsx +103 -0
  316. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/checkbox.tsx +32 -0
  317. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/collapsible.tsx +33 -0
  318. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/datePicker.tsx +127 -0
  319. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/dialog.tsx +162 -0
  320. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/field.tsx +237 -0
  321. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/index.ts +84 -0
  322. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/input.tsx +19 -0
  323. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/label.tsx +22 -0
  324. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/pagination.tsx +132 -0
  325. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/popover.tsx +89 -0
  326. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/select.tsx +193 -0
  327. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/separator.tsx +26 -0
  328. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/skeleton.tsx +14 -0
  329. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/sonner.tsx +20 -0
  330. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/spinner.tsx +16 -0
  331. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/table.tsx +114 -0
  332. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/tabs.tsx +88 -0
  333. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/accountSearchService.ts +46 -0
  334. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/distinctAccountIndustries.graphql +19 -0
  335. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/distinctAccountTypes.graphql +19 -0
  336. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/getAccountDetail.graphql +121 -0
  337. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/searchAccounts.graphql +51 -0
  338. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/AccountObjectDetailPage.tsx +357 -0
  339. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/AccountSearch.tsx +312 -0
  340. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/Home.tsx +34 -0
  341. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/api/objectSearchService.ts +84 -0
  342. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/ActiveFilters.tsx +89 -0
  343. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/FilterContext.tsx +83 -0
  344. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/ObjectBreadcrumb.tsx +66 -0
  345. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/PaginationControls.tsx +109 -0
  346. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/SearchBar.tsx +41 -0
  347. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/SortControl.tsx +143 -0
  348. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/BooleanFilter.tsx +78 -0
  349. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/DateFilter.tsx +128 -0
  350. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/DateRangeFilter.tsx +70 -0
  351. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/FilterFieldWrapper.tsx +33 -0
  352. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/MultiSelectFilter.tsx +97 -0
  353. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/NumericRangeFilter.tsx +163 -0
  354. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/SearchFilter.tsx +50 -0
  355. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/SelectFilter.tsx +97 -0
  356. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/TextFilter.tsx +91 -0
  357. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useAsyncData.ts +54 -0
  358. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useCachedAsyncData.ts +184 -0
  359. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useDebouncedCallback.ts +34 -0
  360. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useObjectSearchParams.ts +252 -0
  361. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/debounce.ts +25 -0
  362. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/fieldUtils.ts +29 -0
  363. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/filterUtils.ts +395 -0
  364. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/sortUtils.ts +38 -0
  365. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/index.ts +6 -0
  366. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/constants.ts +60 -0
  367. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/routeConfig.ts +35 -0
  368. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/utils.ts +6 -0
  369. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/navigationMenu.tsx +80 -0
  370. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/ApplicationSearch.tsx +373 -0
  371. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/Home.tsx +183 -0
  372. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceRequestSearch.tsx +465 -0
  373. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceWorkerSearch.tsx +324 -0
  374. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/NotFound.tsx +18 -0
  375. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/PropertySearch.tsx +258 -0
  376. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/TestAccPage.tsx +19 -0
  377. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/router-utils.tsx +35 -0
  378. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/routes.tsx +63 -0
  379. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/styles/global.css +173 -0
  380. package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/types/conversation.ts +33 -0
  381. package/dist/force-app/main/default/uiBundles/propertymanagementapp/tsconfig.json +42 -0
  382. package/dist/force-app/main/default/uiBundles/propertymanagementapp/tsconfig.node.json +13 -0
  383. package/dist/force-app/main/default/uiBundles/propertymanagementapp/ui-bundle.json +7 -0
  384. package/dist/force-app/main/default/uiBundles/propertymanagementapp/vite-env.d.ts +1 -0
  385. package/dist/force-app/main/default/uiBundles/propertymanagementapp/vite.config.ts +106 -0
  386. package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest-env.d.ts +2 -0
  387. package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest.config.ts +11 -0
  388. package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest.setup.ts +1 -0
  389. package/dist/jest.config.js +6 -0
  390. package/dist/package-lock.json +9995 -0
  391. package/dist/package.json +40 -0
  392. package/dist/scripts/apex/hello.apex +10 -0
  393. package/dist/scripts/graphql-search.sh +191 -0
  394. package/dist/scripts/prepare-import-unique-fields.js +122 -0
  395. package/dist/scripts/setup-cli.mjs +563 -0
  396. package/dist/scripts/sf-project-setup.mjs +66 -0
  397. package/dist/scripts/soql/account.soql +6 -0
  398. package/dist/sfdx-project.json +12 -0
  399. package/package.json +51 -0
@@ -0,0 +1,183 @@
1
+ import { useEffect, useState, useCallback, useMemo } from "react";
2
+ import { useNavigate } from "react-router";
3
+ import { IssuesDonutChart } from "../components/dashboard/IssuesDonutChart";
4
+ import { MaintenanceTable } from "../components/dashboard/MaintenanceTable";
5
+ import { GlobalSearchBar } from "../components/dashboard/GlobalSearchBar";
6
+ import { StatCard } from "../components/dashboard/StatCard";
7
+ import { PageContainer } from "../components/layout/PageContainer";
8
+ import {
9
+ getDashboardMetrics,
10
+ calculateMetrics,
11
+ type DashboardMetrics,
12
+ type DashboardMaintenanceNode,
13
+ } from "../api/dashboard/dashboard";
14
+ import {
15
+ PROPERTY_OBJECT_API_NAME,
16
+ SEARCHABLE_OBJECTS,
17
+ type SearchableObjectConfig,
18
+ } from "../lib/constants";
19
+ import { PATHS } from "../lib/routeConfig";
20
+
21
+ const CHART_ISSUE_TYPES = ["Plumbing", "HVAC", "Electrical", "Appliance", "Pest"] as const;
22
+ const CHART_COLORS = ["#7C3AED", "#EC4899", "#14B8A6", "#06B6D4", "#F59E0B"] as const;
23
+
24
+ export default function Home() {
25
+ const navigate = useNavigate();
26
+
27
+ const [searchQuery, setSearchQuery] = useState("");
28
+ const [selectedObjectApiName, setSelectedObjectApiName] =
29
+ useState<SearchableObjectConfig["objectApiName"]>(PROPERTY_OBJECT_API_NAME);
30
+
31
+ const selectedConfig = useMemo(
32
+ () => SEARCHABLE_OBJECTS.find((o) => o.objectApiName === selectedObjectApiName),
33
+ [selectedObjectApiName],
34
+ );
35
+ const labelPlural = selectedConfig?.fallbackLabelPlural ?? "Records";
36
+
37
+ const [metrics, setMetrics] = useState<DashboardMetrics>({
38
+ totalProperties: 0,
39
+ unitsAvailable: 0,
40
+ occupiedUnits: 0,
41
+ topMaintenanceIssue: "",
42
+ topMaintenanceIssueCount: 0,
43
+ });
44
+ const [metricsLoading, setMetricsLoading] = useState(true);
45
+ const [maintenanceRequests, setMaintenanceRequests] = useState<
46
+ NonNullable<DashboardMaintenanceNode>[]
47
+ >([]);
48
+
49
+ useEffect(() => {
50
+ let cancelled = false;
51
+ (async () => {
52
+ try {
53
+ setMetricsLoading(true);
54
+ const { properties, maintenanceRequests: rawRequests } = await getDashboardMetrics();
55
+ if (!cancelled) {
56
+ setMetrics(calculateMetrics(properties));
57
+ setMaintenanceRequests(rawRequests);
58
+ }
59
+ } catch (error) {
60
+ if (!cancelled) console.error("Error loading dashboard metrics:", error);
61
+ } finally {
62
+ if (!cancelled) setMetricsLoading(false);
63
+ }
64
+ })();
65
+ return () => {
66
+ cancelled = true;
67
+ };
68
+ }, []);
69
+
70
+ const handleSearchSubmit = useCallback(() => {
71
+ const trimmed = searchQuery.trim();
72
+ const path = selectedConfig?.path ?? SEARCHABLE_OBJECTS[0].path;
73
+ if (trimmed) {
74
+ navigate(`${path}?q=${encodeURIComponent(trimmed)}`);
75
+ } else {
76
+ navigate(path);
77
+ }
78
+ }, [searchQuery, navigate, selectedConfig?.path]);
79
+
80
+ const handleBrowseAll = useCallback(() => {
81
+ navigate(selectedConfig?.path ?? SEARCHABLE_OBJECTS[0].path);
82
+ }, [navigate, selectedConfig?.path]);
83
+
84
+ const handleViewMaintenance = useCallback(() => {
85
+ navigate(PATHS.MAINTENANCE_REQUESTS);
86
+ }, [navigate]);
87
+
88
+ const chartData = useMemo(() => {
89
+ const counts: Record<string, number> = {
90
+ Plumbing: 0,
91
+ HVAC: 0,
92
+ Electrical: 0,
93
+ Appliance: 0,
94
+ Pest: 0,
95
+ };
96
+ maintenanceRequests.forEach((request) => {
97
+ const type = request.Type__c?.value || "";
98
+ if (CHART_ISSUE_TYPES.includes(type as (typeof CHART_ISSUE_TYPES)[number])) {
99
+ counts[type]++;
100
+ }
101
+ });
102
+ return [
103
+ { name: "Plumbing", value: counts.Plumbing, color: CHART_COLORS[0] },
104
+ { name: "HVAC", value: counts.HVAC, color: CHART_COLORS[1] },
105
+ { name: "Electrical", value: counts.Electrical, color: CHART_COLORS[2] },
106
+ { name: "Appliance", value: counts.Appliance, color: CHART_COLORS[3] },
107
+ { name: "Pest Control", value: counts.Pest, color: CHART_COLORS[4] },
108
+ ];
109
+ }, [maintenanceRequests]);
110
+
111
+ const trends = useMemo(() => {
112
+ const totalPropertiesTrend = Math.round(metrics.totalProperties * 0.1);
113
+ const unitsAvailableTrend = Math.round(metrics.unitsAvailable * 0.1);
114
+ const occupiedUnitsTrend = Math.round(metrics.occupiedUnits * 0.1);
115
+ return {
116
+ totalProperties: {
117
+ trend: totalPropertiesTrend,
118
+ previous: metrics.totalProperties - totalPropertiesTrend,
119
+ },
120
+ unitsAvailable: {
121
+ trend: unitsAvailableTrend,
122
+ previous: metrics.unitsAvailable + unitsAvailableTrend,
123
+ },
124
+ occupiedUnits: {
125
+ trend: occupiedUnitsTrend,
126
+ previous: metrics.occupiedUnits - occupiedUnitsTrend,
127
+ },
128
+ };
129
+ }, [metrics]);
130
+
131
+ return (
132
+ <PageContainer>
133
+ <div className="max-w-7xl mx-auto space-y-6">
134
+ <GlobalSearchBar
135
+ searchableObjects={SEARCHABLE_OBJECTS}
136
+ selectedObjectApiName={selectedObjectApiName}
137
+ onSelectedObjectChange={setSelectedObjectApiName}
138
+ searchQuery={searchQuery}
139
+ onSearchQueryChange={setSearchQuery}
140
+ onSearchSubmit={handleSearchSubmit}
141
+ onBrowseAll={handleBrowseAll}
142
+ labelPlural={labelPlural}
143
+ />
144
+
145
+ <div className="grid grid-cols-1 lg:grid-cols-[70%_30%] gap-6">
146
+ <div className="space-y-6">
147
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
148
+ <StatCard
149
+ title="Total Properties"
150
+ loading={metricsLoading}
151
+ value={metrics.totalProperties}
152
+ trend={{ value: trends.totalProperties.trend, isPositive: true }}
153
+ subtitle={`Last month total ${trends.totalProperties.previous}`}
154
+ />
155
+ <StatCard
156
+ title="Units Available"
157
+ loading={metricsLoading}
158
+ value={metrics.unitsAvailable}
159
+ trend={{ value: trends.unitsAvailable.trend, isPositive: false }}
160
+ subtitle={`Last month total ${trends.unitsAvailable.previous}/${metrics.totalProperties}`}
161
+ />
162
+ <StatCard
163
+ title="Occupied Units"
164
+ loading={metricsLoading}
165
+ value={metrics.occupiedUnits}
166
+ trend={{ value: trends.occupiedUnits.trend, isPositive: true }}
167
+ subtitle={`Last month total ${trends.occupiedUnits.previous}`}
168
+ />
169
+ </div>
170
+ <MaintenanceTable
171
+ requests={maintenanceRequests}
172
+ loading={metricsLoading}
173
+ onView={handleViewMaintenance}
174
+ />
175
+ </div>
176
+ <div>
177
+ <IssuesDonutChart data={chartData} loading={metricsLoading} />
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </PageContainer>
182
+ );
183
+ }
@@ -0,0 +1,465 @@
1
+ import { useMemo, useState } from "react";
2
+ import { useNavigate } from "react-router";
3
+ import { toast } from "../components/ui/sonner";
4
+ import {
5
+ searchMaintenanceRequests,
6
+ fetchDistinctMaintenanceRequestStatus,
7
+ fetchDistinctMaintenanceRequestType,
8
+ fetchDistinctMaintenanceRequestPriority,
9
+ type MaintenanceRequestSearchNode,
10
+ } from "../api/maintenanceRequests/maintenanceRequestSearchService";
11
+ import { useCachedAsyncData } from "../features/object-search/hooks/useCachedAsyncData";
12
+ import {
13
+ useObjectSearchParams,
14
+ type UseObjectSearchParamsReturn,
15
+ } from "../features/object-search/hooks/useObjectSearchParams";
16
+ import type { FilterFieldConfig } from "../features/object-search/utils/filterUtils";
17
+ import type { SortFieldConfig } from "../features/object-search/utils/sortUtils";
18
+ import { PageHeader } from "../components/layout/PageHeader";
19
+ import { PageContainer } from "../components/layout/PageContainer";
20
+ import {
21
+ FilterProvider,
22
+ FilterResetButton,
23
+ } from "../features/object-search/components/FilterContext";
24
+ import { FilterRow } from "../components/layout/FilterRow";
25
+ import { SearchFilter } from "../features/object-search/components/filters/SearchFilter";
26
+ import { MultiSelectFilter } from "../features/object-search/components/filters/MultiSelectFilter";
27
+ import { DateFilter } from "../features/object-search/components/filters/DateFilter";
28
+ import { ObjectSearchErrorState } from "../components/shared/ObjectSearchErrorState";
29
+ import PaginationControls from "../features/object-search/components/PaginationControls";
30
+ import { UserAvatar } from "../components/shared/UserAvatar";
31
+ import { Skeleton } from "../components/ui/skeleton";
32
+ import {
33
+ Table,
34
+ TableHeader,
35
+ TableBody,
36
+ TableRow,
37
+ TableHead,
38
+ TableCell,
39
+ } from "../components/ui/table";
40
+ import { Badge } from "../components/ui/badge";
41
+ import { Check } from "lucide-react";
42
+ import { MaintenanceDetailsModal } from "../components/maintenanceRequests/MaintenanceDetailsModal";
43
+ import { updateMaintenanceStatus } from "../api/maintenanceRequests/maintenanceRequests";
44
+ import PlumbingIcon from "../assets/icons/plumbing.svg";
45
+ import HVACIcon from "../assets/icons/hvac.svg";
46
+ import ElectricalIcon from "../assets/icons/electrical.svg";
47
+ import AppliancesIcon from "../assets/icons/appliances.svg";
48
+ import PestIcon from "../assets/icons/pest.svg";
49
+ import { PAGINATION_CONFIG } from "../lib/constants";
50
+ import type {
51
+ Maintenance_Request__C_Filter,
52
+ Maintenance_Request__C_OrderBy,
53
+ } from "../api/graphql-operations-types";
54
+ import { ResultOrder } from "../api/graphql-operations-types";
55
+ import { cn } from "../lib/utils";
56
+
57
+ const issueIcons: Record<string, string> = {
58
+ Plumbing: PlumbingIcon,
59
+ HVAC: HVACIcon,
60
+ Electrical: ElectricalIcon,
61
+ Appliance: AppliancesIcon,
62
+ Pest: PestIcon,
63
+ };
64
+
65
+ const FILTER_CONFIGS: FilterFieldConfig[] = [
66
+ {
67
+ field: "search",
68
+ label: "Search",
69
+ type: "search",
70
+ searchFields: ["Name"],
71
+ placeholder: "Search by name...",
72
+ },
73
+ { field: "Status__c", label: "Status", type: "picklist" },
74
+ { field: "Type__c", label: "Type", type: "picklist" },
75
+ { field: "Priority__c", label: "Priority", type: "picklist" },
76
+ { field: "Scheduled__c", label: "Scheduled", type: "datetime" },
77
+ ];
78
+
79
+ const SORT_CONFIGS: SortFieldConfig<string>[] = [
80
+ { field: "Name", label: "Subject" },
81
+ { field: "Status__c", label: "Status" },
82
+ { field: "Priority__c", label: "Priority" },
83
+ { field: "Scheduled__c", label: "Scheduled" },
84
+ { field: "CreatedDate", label: "Created Date" },
85
+ ];
86
+
87
+ export default function MaintenanceRequestSearch() {
88
+ const [selectedRequest, setSelectedRequest] = useState<MaintenanceRequestSearchNode | null>(null);
89
+
90
+ const { data: statusOptions } = useCachedAsyncData(fetchDistinctMaintenanceRequestStatus, [], {
91
+ key: "distinctMaintenanceRequestStatus",
92
+ ttl: 30_000,
93
+ });
94
+ const { data: typeOptions } = useCachedAsyncData(fetchDistinctMaintenanceRequestType, [], {
95
+ key: "distinctMaintenanceRequestType",
96
+ ttl: 30_000,
97
+ });
98
+ const { data: priorityOptions } = useCachedAsyncData(
99
+ fetchDistinctMaintenanceRequestPriority,
100
+ [],
101
+ { key: "distinctMaintenanceRequestPriority", ttl: 30_000 },
102
+ );
103
+
104
+ const { filters, query, pagination, resetAll } = useObjectSearchParams<
105
+ Maintenance_Request__C_Filter,
106
+ Maintenance_Request__C_OrderBy
107
+ >(FILTER_CONFIGS, SORT_CONFIGS, PAGINATION_CONFIG);
108
+ const effectiveOrderBy = useMemo<Maintenance_Request__C_OrderBy>(
109
+ () => query.orderBy ?? { CreatedDate: { order: ResultOrder.Desc } },
110
+ [query.orderBy],
111
+ );
112
+ const searchKey = `maintenance-requests:${JSON.stringify({ where: query.where, orderBy: effectiveOrderBy, first: pagination.pageSize, after: pagination.afterCursor })}`;
113
+ const { data, loading, error } = useCachedAsyncData(
114
+ () =>
115
+ searchMaintenanceRequests({
116
+ where: query.where,
117
+ orderBy: effectiveOrderBy,
118
+ first: pagination.pageSize,
119
+ after: pagination.afterCursor,
120
+ }),
121
+ [query.where, effectiveOrderBy, pagination.pageSize, pagination.afterCursor],
122
+ { key: searchKey },
123
+ );
124
+
125
+ const validMaintenanceRequestNodes = useMemo(
126
+ () =>
127
+ (data?.edges ?? []).reduce<MaintenanceRequestSearchNode[]>((acc, edge) => {
128
+ if (edge?.node) acc.push(edge.node);
129
+ return acc;
130
+ }, []),
131
+ [data?.edges],
132
+ );
133
+
134
+ const pageInfo = data?.pageInfo;
135
+ const hasNextPage = pageInfo?.hasNextPage ?? false;
136
+ const hasPreviousPage = pagination.pageIndex > 0;
137
+
138
+ const handleSaveStatus = async (requestId: string, status: string) => {
139
+ try {
140
+ const success = await updateMaintenanceStatus(requestId, status);
141
+ if (success) {
142
+ if (selectedRequest?.Id === requestId) {
143
+ setSelectedRequest({ ...selectedRequest, Status__c: { value: status } });
144
+ }
145
+ toast.success("Status updated", {
146
+ description: "Maintenance request status has been updated successfully.",
147
+ });
148
+ } else {
149
+ toast.error("Update failed", {
150
+ description: "Failed to update maintenance request status. Please try again.",
151
+ });
152
+ }
153
+ } catch (err) {
154
+ console.error(err);
155
+ toast.error("Error updating status", {
156
+ description: "An error occurred while updating the status. Please try again.",
157
+ });
158
+ }
159
+ };
160
+
161
+ return (
162
+ <>
163
+ <PageContainer>
164
+ <PageHeader
165
+ title="Maintenance Requests"
166
+ description="Track and manage maintenance requests"
167
+ />
168
+ <MaintenanceRequestSearchFilters
169
+ filters={filters}
170
+ statusOptions={statusOptions ?? []}
171
+ typeOptions={typeOptions ?? []}
172
+ priorityOptions={priorityOptions ?? []}
173
+ resetAll={resetAll}
174
+ />
175
+
176
+ <div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
177
+ <Table>
178
+ <MaintenanceRequestSearchTableHeader />
179
+ <TableBody>
180
+ {loading && <MaintenanceRequestSearchSkeleton pageSize={pagination.pageSize} />}
181
+
182
+ {!loading && error && <MaintenanceRequestSearchErrorState />}
183
+
184
+ {!loading && !error && validMaintenanceRequestNodes.length === 0 && (
185
+ <MaintenanceRequestSearchNoResults />
186
+ )}
187
+
188
+ {!loading && !error && validMaintenanceRequestNodes.length > 0 && (
189
+ <MaintenanceRequestSearchTable
190
+ requestNodes={validMaintenanceRequestNodes}
191
+ setSelectedRequest={setSelectedRequest}
192
+ />
193
+ )}
194
+ </TableBody>
195
+ </Table>
196
+ </div>
197
+
198
+ <PaginationControls
199
+ pageIndex={pagination.pageIndex}
200
+ hasNextPage={hasNextPage}
201
+ hasPreviousPage={hasPreviousPage}
202
+ pageSize={pagination.pageSize}
203
+ pageSizeOptions={PAGINATION_CONFIG.validPageSizes}
204
+ onNextPage={() => {
205
+ if (pageInfo?.endCursor) pagination.goToNextPage(pageInfo.endCursor);
206
+ }}
207
+ onPreviousPage={pagination.goToPreviousPage}
208
+ onPageSizeChange={pagination.setPageSize}
209
+ disabled={loading || !!error}
210
+ />
211
+ </PageContainer>
212
+
213
+ {!loading && !error && selectedRequest && (
214
+ <MaintenanceDetailsModal
215
+ request={selectedRequest}
216
+ isOpen={!!selectedRequest}
217
+ onClose={() => setSelectedRequest(null)}
218
+ onSave={handleSaveStatus}
219
+ />
220
+ )}
221
+ </>
222
+ );
223
+ }
224
+
225
+ function MaintenanceRequestSearchFilters({
226
+ filters,
227
+ statusOptions,
228
+ typeOptions,
229
+ priorityOptions,
230
+ resetAll,
231
+ }: {
232
+ filters: UseObjectSearchParamsReturn<
233
+ Maintenance_Request__C_Filter,
234
+ Maintenance_Request__C_OrderBy
235
+ >["filters"];
236
+ statusOptions: Array<{ value: string; label: string }>;
237
+ typeOptions: Array<{ value: string; label: string }>;
238
+ priorityOptions: Array<{ value: string; label: string }>;
239
+ resetAll: () => void;
240
+ }) {
241
+ return (
242
+ <FilterProvider
243
+ filters={filters.active}
244
+ onFilterChange={filters.set}
245
+ onFilterRemove={filters.remove}
246
+ onReset={resetAll}
247
+ >
248
+ <FilterRow ariaLabel="Maintenance Requests filters">
249
+ <SearchFilter
250
+ field="search"
251
+ label="Search"
252
+ placeholder="Search by name..."
253
+ className="w-full sm:w-50"
254
+ />
255
+ <MultiSelectFilter
256
+ field="Status__c"
257
+ label="Status"
258
+ options={statusOptions}
259
+ className="w-full sm:w-36"
260
+ />
261
+ <MultiSelectFilter
262
+ field="Type__c"
263
+ label="Type"
264
+ options={typeOptions}
265
+ className="w-full sm:w-36"
266
+ />
267
+ <MultiSelectFilter
268
+ field="Priority__c"
269
+ label="Priority"
270
+ options={priorityOptions}
271
+ className="w-full sm:w-36"
272
+ />
273
+ <DateFilter
274
+ field="Scheduled__c"
275
+ label="Scheduled"
276
+ filterType="datetime"
277
+ className="w-full sm:w-56"
278
+ />
279
+ <FilterResetButton />
280
+ </FilterRow>
281
+ </FilterProvider>
282
+ );
283
+ }
284
+
285
+ function MaintenanceRequestSearchTableHeader() {
286
+ return (
287
+ <TableHeader>
288
+ <TableRow>
289
+ <TableHead className="w-4/12 max-w-xs px-6 py-4 bg-gray-50 text-sm font-semibold text-purple-700 uppercase tracking-wide">
290
+ Maintenance Task
291
+ </TableHead>
292
+ <TableHead className="w-3/12 px-6 py-4 bg-gray-50 text-sm font-semibold text-purple-700 uppercase tracking-wide">
293
+ Tenant Unit
294
+ </TableHead>
295
+ <TableHead className="w-3/12 px-6 py-4 bg-gray-50 text-sm font-semibold text-purple-700 uppercase tracking-wide">
296
+ Assigned Worker
297
+ </TableHead>
298
+ <TableHead className="w-2/12 px-6 py-4 bg-gray-50 text-sm font-semibold text-purple-700 uppercase tracking-wide">
299
+ Status
300
+ </TableHead>
301
+ </TableRow>
302
+ </TableHeader>
303
+ );
304
+ }
305
+
306
+ function MaintenanceRequestSearchNoResults() {
307
+ return (
308
+ <TableRow>
309
+ <TableCell colSpan={4} className="text-center py-12 text-gray-500">
310
+ No maintenance requests found
311
+ </TableCell>
312
+ </TableRow>
313
+ );
314
+ }
315
+
316
+ function MaintenanceRequestSearchTable({
317
+ requestNodes,
318
+ setSelectedRequest,
319
+ }: {
320
+ requestNodes: MaintenanceRequestSearchNode[];
321
+ setSelectedRequest: (request: MaintenanceRequestSearchNode) => void;
322
+ }) {
323
+ return (
324
+ <>
325
+ {requestNodes.map((request) => {
326
+ const issueType = request.Type__c?.value ?? "";
327
+ const description = request.Description__c?.value ?? "";
328
+ const tenantName = request.User__r?.Name?.value || "Unknown";
329
+ const tenantUnit =
330
+ request.Property__r?.Name?.value || request.Property__r?.Address__c?.value || "";
331
+ const assignedWorkerName = request.Assigned_Worker__r?.Name?.value || "Unassigned";
332
+ const status = request.Status__c?.value || "New";
333
+ const imageVersionId =
334
+ request.ContentDocumentLinks?.edges?.[0]?.node?.ContentDocument?.LatestPublishedVersionId
335
+ ?.value;
336
+ const imageUrl = imageVersionId
337
+ ? `/sfc/servlet.shepherd/version/download/${imageVersionId}`
338
+ : undefined;
339
+ return (
340
+ <TableRow
341
+ key={request.Id}
342
+ onClick={() => setSelectedRequest(request)}
343
+ className="hover:bg-gray-50 transition-colors cursor-pointer"
344
+ >
345
+ <TableCell className="max-w-xs px-6 py-5">
346
+ <div className="flex items-center gap-4">
347
+ <div className="w-16 h-16 rounded-lg flex-shrink-0 overflow-hidden flex items-center justify-center bg-purple-100">
348
+ {imageUrl ? (
349
+ <img src={imageUrl} alt={description} className="w-full h-full object-cover" />
350
+ ) : issueIcons[issueType] ? (
351
+ <img src={issueIcons[issueType]} alt={issueType} className="w-8 h-8" />
352
+ ) : (
353
+ <span className="text-2xl">🔧</span>
354
+ )}
355
+ </div>
356
+ <div className="flex-1 min-w-0">
357
+ <h3 className="font-semibold text-gray-900 truncate mb-1">{description}</h3>
358
+ <p className="text-sm text-gray-500">By Tenant</p>
359
+ </div>
360
+ </div>
361
+ </TableCell>
362
+ <TableCell className="px-6 py-5">
363
+ <div className="flex items-center gap-3 min-w-0">
364
+ <UserAvatar name={tenantName} size="md" />
365
+ <div className="min-w-0 flex-1">
366
+ <p className="font-medium text-gray-900 truncate">{tenantName}</p>
367
+ <p className="text-gray-500 truncate">{tenantUnit}</p>
368
+ </div>
369
+ </div>
370
+ </TableCell>
371
+ <TableCell className="px-6 py-5">
372
+ <p className="text-gray-900 truncate">{assignedWorkerName}</p>
373
+ </TableCell>
374
+ <TableCell className="px-6 py-5">
375
+ <StatusBadge status={status} />
376
+ </TableCell>
377
+ </TableRow>
378
+ );
379
+ })}
380
+ </>
381
+ );
382
+ }
383
+
384
+ function StatusBadge({ status }: { status: string }) {
385
+ const statusLower = status.toLowerCase();
386
+
387
+ const style =
388
+ statusLower === "new"
389
+ ? "bg-pink-100 text-pink-700"
390
+ : statusLower === "in progress"
391
+ ? "bg-yellow-100 text-yellow-700"
392
+ : statusLower === "resolved"
393
+ ? "bg-green-100 text-green-700"
394
+ : "bg-gray-100 text-gray-700";
395
+
396
+ const label =
397
+ statusLower === "new"
398
+ ? "Needs Action"
399
+ : statusLower === "in progress"
400
+ ? "In Progress"
401
+ : statusLower === "resolved"
402
+ ? "Resolved"
403
+ : status;
404
+
405
+ return (
406
+ <Badge className={cn("text-sm", style)}>
407
+ {statusLower === "resolved" && <Check className="w-4 h-4" />}
408
+ {(statusLower === "new" || statusLower === "in progress") && (
409
+ <span className="w-2 h-2 rounded-full bg-current" />
410
+ )}
411
+ {label}
412
+ </Badge>
413
+ );
414
+ }
415
+
416
+ function MaintenanceRequestSearchSkeleton({ pageSize }: { pageSize: number }) {
417
+ return (
418
+ <>
419
+ {Array.from({ length: pageSize }, (_, i) => (
420
+ <TableRow key={i}>
421
+ <TableCell className="px-6 py-5">
422
+ <div className="flex items-center gap-4">
423
+ <Skeleton className="h-16 w-16 rounded-lg shrink-0" />
424
+ <div className="space-y-2 flex-1 min-w-0">
425
+ <Skeleton className="h-4 w-full" />
426
+ <Skeleton className="h-3 w-20" />
427
+ </div>
428
+ </div>
429
+ </TableCell>
430
+ <TableCell className="px-6 py-5">
431
+ <div className="flex items-center gap-3">
432
+ <Skeleton className="h-10 w-10 rounded-full shrink-0" />
433
+ <div className="space-y-2 min-w-0">
434
+ <Skeleton className="h-4 w-24" />
435
+ <Skeleton className="h-3 w-32" />
436
+ </div>
437
+ </div>
438
+ </TableCell>
439
+ <TableCell className="px-6 py-5">
440
+ <Skeleton className="h-4 w-28" />
441
+ </TableCell>
442
+ <TableCell className="px-6 py-5">
443
+ <Skeleton className="h-6 w-20 rounded-full" />
444
+ </TableCell>
445
+ </TableRow>
446
+ ))}
447
+ </>
448
+ );
449
+ }
450
+
451
+ function MaintenanceRequestSearchErrorState() {
452
+ const navigate = useNavigate();
453
+
454
+ return (
455
+ <TableRow>
456
+ <TableCell colSpan={4} className="p-0">
457
+ <ObjectSearchErrorState
458
+ message="There was an error loading the maintenance requests. Please try again."
459
+ onGoHome={() => navigate("/")}
460
+ onRetry={() => navigate(0)}
461
+ />
462
+ </TableCell>
463
+ </TableRow>
464
+ );
465
+ }