@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,142 @@
1
+ import React, { useState } from "react";
2
+ import { X } from "lucide-react";
3
+ import { Button } from "../ui/button";
4
+ import type { ApplicationSearchNode } from "../../api/applications/applicationSearchService";
5
+
6
+ interface ApplicationDetailsModalProps {
7
+ application: ApplicationSearchNode;
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ onSave: (applicationId: string, status: string) => Promise<void>;
11
+ }
12
+
13
+ export const ApplicationDetailsModal: React.FC<ApplicationDetailsModalProps> = ({
14
+ application,
15
+ isOpen,
16
+ onClose,
17
+ onSave,
18
+ }) => {
19
+ const status = application.Status__c?.value || "Unknown";
20
+ const [selectedStatus, setSelectedStatus] = useState(status);
21
+ const [isSaving, setIsSaving] = useState(false);
22
+
23
+ const isStatusEditable =
24
+ status.toLowerCase() !== "approved" && status.toLowerCase() !== "rejected";
25
+
26
+ const statusOptions = ["Submitted", "Background Check", "Under Review", "Approved", "Rejected"];
27
+
28
+ const handleSave = async () => {
29
+ if (!isStatusEditable) return;
30
+
31
+ setIsSaving(true);
32
+ try {
33
+ await onSave(application.Id, selectedStatus);
34
+ onClose();
35
+ } catch (error) {
36
+ console.error("Error saving status:", error);
37
+ } finally {
38
+ setIsSaving(false);
39
+ }
40
+ };
41
+
42
+ if (!isOpen) return null;
43
+
44
+ const applicantName = application.User__r?.Name?.value || "Unknown";
45
+ const propertyName = application.Property__r?.Name?.value;
46
+ const propertyAddress = application.Property__r?.Address__c?.value || "";
47
+ const employment = application.Employment__c?.value;
48
+ const references = application.References__c?.value;
49
+
50
+ return (
51
+ <div className="fixed inset-0 z-50 flex items-center justify-center">
52
+ <div className="fixed inset-0 bg-black/50" onClick={onClose} />
53
+
54
+ <div className="relative bg-white rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
55
+ <div className="flex items-center justify-between p-6 border-b border-gray-200">
56
+ <h2 className="text-xl font-semibold text-gray-900">Application Details</h2>
57
+ <button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
58
+ <X className="w-6 h-6" />
59
+ </button>
60
+ </div>
61
+
62
+ <div className="p-6 space-y-6">
63
+ <div>
64
+ <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
65
+ Applicant
66
+ </h3>
67
+ <p className="text-lg font-medium text-gray-900">{applicantName}</p>
68
+ </div>
69
+
70
+ <div>
71
+ <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
72
+ Property
73
+ </h3>
74
+ <p className="text-base text-gray-900">
75
+ {propertyName && <span className="font-medium">{propertyName}</span>}
76
+ </p>
77
+ <p className="text-sm text-gray-600">{propertyAddress}</p>
78
+ </div>
79
+
80
+ {employment && (
81
+ <div>
82
+ <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
83
+ Employment
84
+ </h3>
85
+ <p className="text-sm text-gray-700 whitespace-pre-wrap">{employment}</p>
86
+ </div>
87
+ )}
88
+
89
+ {references && (
90
+ <div>
91
+ <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
92
+ References
93
+ </h3>
94
+ <p className="text-sm text-gray-700 whitespace-pre-wrap">{references}</p>
95
+ </div>
96
+ )}
97
+
98
+ <div>
99
+ <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
100
+ Status
101
+ </h3>
102
+ {isStatusEditable ? (
103
+ <select
104
+ value={selectedStatus}
105
+ onChange={(e) => setSelectedStatus(e.target.value)}
106
+ className="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500 focus:border-transparent"
107
+ >
108
+ {statusOptions.map((s) => (
109
+ <option key={s} value={s}>
110
+ {s}
111
+ </option>
112
+ ))}
113
+ </select>
114
+ ) : (
115
+ <div className="flex items-center">
116
+ <span className="px-4 py-2 bg-gray-100 text-gray-700 rounded-md font-medium">
117
+ {status}
118
+ </span>
119
+ <span className="ml-3 text-sm text-gray-500">(Cannot be modified)</span>
120
+ </div>
121
+ )}
122
+ </div>
123
+ </div>
124
+
125
+ <div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200">
126
+ <Button variant="outline" onClick={onClose} disabled={isSaving}>
127
+ Close
128
+ </Button>
129
+ {isStatusEditable && (
130
+ <Button
131
+ onClick={handleSave}
132
+ disabled={isSaving || selectedStatus === status}
133
+ className="bg-purple-600 hover:bg-purple-700"
134
+ >
135
+ {isSaving ? "Saving..." : "Save Changes"}
136
+ </Button>
137
+ )}
138
+ </div>
139
+ </div>
140
+ </div>
141
+ );
142
+ };
@@ -0,0 +1,101 @@
1
+ import type { SearchableObjectConfig } from "../../lib/constants";
2
+ import {
3
+ Select,
4
+ SelectContent,
5
+ SelectItem,
6
+ SelectTrigger,
7
+ SelectValue,
8
+ } from "../ui/select";
9
+ import { Search } from "lucide-react";
10
+
11
+ type SearchableObjectApiName = SearchableObjectConfig["objectApiName"];
12
+
13
+ export interface GlobalSearchBarProps {
14
+ searchableObjects: readonly SearchableObjectConfig[];
15
+ selectedObjectApiName: SearchableObjectApiName;
16
+ onSelectedObjectChange: (objectApiName: SearchableObjectApiName) => void;
17
+ searchQuery: string;
18
+ onSearchQueryChange: (value: string) => void;
19
+ onSearchSubmit: () => void;
20
+ onBrowseAll: () => void;
21
+ labelPlural: string;
22
+ }
23
+
24
+ /**
25
+ * Home page search: object dropdown + search input. Uses fallback labels from config.
26
+ */
27
+ export function GlobalSearchBar({
28
+ searchableObjects,
29
+ selectedObjectApiName,
30
+ onSelectedObjectChange,
31
+ searchQuery,
32
+ onSearchQueryChange,
33
+ onSearchSubmit,
34
+ onBrowseAll,
35
+ labelPlural,
36
+ }: GlobalSearchBarProps) {
37
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
38
+ if (e.key === "Enter") {
39
+ e.preventDefault();
40
+ onSearchSubmit();
41
+ }
42
+ };
43
+
44
+ return (
45
+ <div className="flex flex-wrap gap-2 items-center mb-4">
46
+ <div
47
+ className="w-full max-w-xl bg-white rounded-full px-4 py-3 shadow-sm border border-gray-200 flex items-center gap-2"
48
+ role="search"
49
+ aria-label={`Search ${labelPlural}`}
50
+ >
51
+ <Select
52
+ value={selectedObjectApiName}
53
+ onValueChange={(v) => onSelectedObjectChange(v as SearchableObjectApiName)}
54
+ >
55
+ <SelectTrigger
56
+ className="border-0 bg-transparent shadow-none focus:ring-0 focus:ring-offset-0 min-w-[120px] py-0 h-auto font-medium text-gray-700"
57
+ aria-label="Search in"
58
+ >
59
+ <SelectValue />
60
+ </SelectTrigger>
61
+ <SelectContent>
62
+ {searchableObjects.map((obj) => (
63
+ <SelectItem key={obj.objectApiName} value={obj.objectApiName}>
64
+ {obj.fallbackLabelPlural ?? "Records"}
65
+ </SelectItem>
66
+ ))}
67
+ </SelectContent>
68
+ </Select>
69
+ <span className="text-gray-300 shrink-0" aria-hidden="true">
70
+ |
71
+ </span>
72
+ <input
73
+ type="search"
74
+ placeholder={`Search ${labelPlural}`}
75
+ value={searchQuery}
76
+ onChange={(e) => onSearchQueryChange(e.target.value)}
77
+ onKeyDown={handleKeyDown}
78
+ className="flex-1 outline-none text-gray-600 bg-transparent min-w-0"
79
+ aria-label={`Search ${labelPlural}`}
80
+ />
81
+ <button
82
+ type="button"
83
+ onClick={onSearchSubmit}
84
+ disabled={!searchQuery.trim()}
85
+ className="p-1 rounded-full hover:bg-gray-100 disabled:opacity-50 disabled:pointer-events-none shrink-0"
86
+ aria-label="Submit search"
87
+ >
88
+ <Search className="w-5 h-5 text-gray-500" aria-hidden="true" />
89
+ </button>
90
+ </div>
91
+ <button
92
+ type="button"
93
+ onClick={onBrowseAll}
94
+ className="px-4 py-3 text-sm font-medium text-[#372949] bg-white border border-gray-200 rounded-full shadow-sm hover:bg-gray-50 whitespace-nowrap"
95
+ aria-label={`Browse all ${labelPlural}`}
96
+ >
97
+ Browse all {labelPlural}
98
+ </button>
99
+ </div>
100
+ );
101
+ }
@@ -0,0 +1,122 @@
1
+ import React from "react";
2
+ import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from "recharts";
3
+ import { Card } from "../ui/card";
4
+ import { Skeleton } from "../ui/skeleton";
5
+ import { MoreVertical } from "lucide-react";
6
+
7
+ interface ChartData {
8
+ name: string;
9
+ value: number;
10
+ color: string;
11
+ }
12
+
13
+ interface IssuesDonutChartProps {
14
+ data: ChartData[];
15
+ loading?: boolean;
16
+ }
17
+
18
+ interface CustomTooltipProps {
19
+ active?: boolean;
20
+ payload?: Array<{ name?: string | number; value?: number }>;
21
+ total: number;
22
+ }
23
+
24
+ function CustomTooltip({ active, payload, total }: CustomTooltipProps) {
25
+ if (active && payload && payload.length && payload[0].value != null) {
26
+ const percentage = total > 0 ? Math.round((payload[0].value / total) * 100) : 0;
27
+ const name = payload[0].name != null ? String(payload[0].name) : "";
28
+ return (
29
+ <div className="bg-white p-3 border border-gray-200 rounded shadow-lg z-50">
30
+ <p className="text-sm font-semibold text-gray-800">{name}</p>
31
+ <p className="text-sm text-gray-600">
32
+ Count: <span className="font-medium">{payload[0].value}</span>
33
+ </p>
34
+ <p className="text-sm text-gray-600">
35
+ Percentage: <span className="font-medium">{percentage}%</span>
36
+ </p>
37
+ </div>
38
+ );
39
+ }
40
+ return null;
41
+ }
42
+
43
+ export const IssuesDonutChart: React.FC<IssuesDonutChartProps> = ({ data, loading }) => {
44
+ const total = data.reduce((sum, item) => sum + item.value, 0);
45
+ const maxValue = data.length > 0 ? Math.max(...data.map((item) => item.value)) : 0;
46
+ const mainPercentage = total > 0 ? Math.round((maxValue / total) * 100) : 0;
47
+
48
+ return (
49
+ <Card className="p-4 border-gray-200 shadow-sm flex flex-col relative">
50
+ {/* Three-dot menu */}
51
+ <button className="absolute top-4 right-4 p-1 hover:bg-gray-100 rounded-md transition-colors z-10">
52
+ <MoreVertical className="w-4 h-4 text-gray-400" />
53
+ </button>
54
+
55
+ <h3 className="text-sm font-medium text-primary-purple mb-2 uppercase tracking-wide">
56
+ Top Maintenance Issues
57
+ </h3>
58
+ {loading ? (
59
+ <>
60
+ <div className="flex items-center justify-center" style={{ height: 300 }}>
61
+ <div className="h-[220px] w-[220px] rounded-full border-[40px] border-muted animate-pulse" />
62
+ </div>
63
+ <div className="mt-6 grid grid-cols-2 gap-6">
64
+ {Array.from({ length: 5 }, (_, i) => (
65
+ <div key={i} className="flex items-center gap-2">
66
+ <Skeleton className="w-3 h-3 rounded-full" />
67
+ <Skeleton className="h-3 w-20" />
68
+ </div>
69
+ ))}
70
+ </div>
71
+ </>
72
+ ) : (
73
+ <>
74
+ <div className="relative flex items-center justify-center">
75
+ <ResponsiveContainer width="100%" height={300}>
76
+ <PieChart>
77
+ <Pie
78
+ data={data}
79
+ cx="50%"
80
+ cy="50%"
81
+ innerRadius={70}
82
+ outerRadius={110}
83
+ paddingAngle={2}
84
+ dataKey="value"
85
+ >
86
+ {data.map((entry, index) => (
87
+ <Cell key={`cell-${index}`} fill={entry.color} />
88
+ ))}
89
+ </Pie>
90
+ <Tooltip
91
+ content={(props) => (
92
+ <CustomTooltip
93
+ active={props.active}
94
+ payload={props.payload as CustomTooltipProps["payload"]}
95
+ total={total}
96
+ />
97
+ )}
98
+ wrapperStyle={{ zIndex: 1000 }}
99
+ />
100
+ </PieChart>
101
+ </ResponsiveContainer>
102
+ {/* Center text */}
103
+ <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
104
+ <div className="text-center">
105
+ <div className="text-5xl font-bold text-primary-purple">{mainPercentage}%</div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ {/* Legend */}
110
+ <div className="mt-6 grid grid-cols-2 gap-3">
111
+ {data.map((item, index) => (
112
+ <div key={index} className="flex items-center gap-2">
113
+ <div className="w-3 h-3 rounded-full" style={{ backgroundColor: item.color }}></div>
114
+ <span className="text-sm text-gray-700">{item.name}</span>
115
+ </div>
116
+ ))}
117
+ </div>
118
+ </>
119
+ )}
120
+ </Card>
121
+ );
122
+ };
@@ -0,0 +1,129 @@
1
+ import React from "react";
2
+ import { useNavigate } from "react-router";
3
+ import { PATHS } from "../../lib/routeConfig";
4
+ import { Card } from "../ui/card";
5
+ import { Button } from "../ui/button";
6
+ import { Skeleton } from "../ui/skeleton";
7
+ import type { DashboardMaintenanceNode } from "../../api/dashboard/dashboard";
8
+ import PlumbingIcon from "../../assets/icons/plumbing.svg";
9
+ import HVACIcon from "../../assets/icons/hvac.svg";
10
+ import ElectricalIcon from "../../assets/icons/electrical.svg";
11
+ import AppliancesIcon from "../../assets/icons/appliances.svg";
12
+ import PestIcon from "../../assets/icons/pest.svg";
13
+
14
+ interface MaintenanceTableProps {
15
+ requests: NonNullable<DashboardMaintenanceNode>[];
16
+ loading?: boolean;
17
+ onView?: (id: string) => void;
18
+ }
19
+
20
+ const issueIcons: Record<string, string> = {
21
+ Plumbing: PlumbingIcon,
22
+ HVAC: HVACIcon,
23
+ Electrical: ElectricalIcon,
24
+ Appliance: AppliancesIcon,
25
+ Pest: PestIcon,
26
+ };
27
+
28
+ const issueIconColors: Record<string, string> = {
29
+ Plumbing: "bg-purple-100",
30
+ HVAC: "bg-purple-100",
31
+ Electrical: "bg-purple-100",
32
+ Appliance: "bg-purple-100",
33
+ Pest: "bg-purple-100",
34
+ };
35
+
36
+ export const MaintenanceTable: React.FC<MaintenanceTableProps> = ({ requests, loading }) => {
37
+ const navigate = useNavigate();
38
+
39
+ const handleSeeAll = () => {
40
+ navigate(PATHS.MAINTENANCE_REQUESTS);
41
+ };
42
+
43
+ return (
44
+ <Card className="p-6 border-gray-200 shadow-sm">
45
+ <div className="flex items-center justify-between mb-6">
46
+ <h2 className="text-lg font-semibold text-primary-purple uppercase tracking-wide">
47
+ Maintenance Requests
48
+ </h2>
49
+ <Button variant="link" onClick={handleSeeAll} className="cursor-pointer">
50
+ See All
51
+ </Button>
52
+ </div>
53
+ <div className="space-y-4">
54
+ {loading ? (
55
+ Array.from({ length: 5 }, (_, i) => (
56
+ <div key={i} className="flex items-center p-4 bg-gray-50 rounded-lg">
57
+ <Skeleton className="w-12 h-12 rounded-lg shrink-0" />
58
+ <div className="ml-4 w-64 shrink-0 space-y-2">
59
+ <Skeleton className="h-4 w-40" />
60
+ <Skeleton className="h-3 w-32" />
61
+ </div>
62
+ <div className="ml-4 w-80 shrink-0">
63
+ <Skeleton className="h-3 w-56" />
64
+ </div>
65
+ <div className="ml-4 w-48 shrink-0 flex items-center gap-2">
66
+ <Skeleton className="w-8 h-8 rounded-full shrink-0" />
67
+ <Skeleton className="h-4 w-24" />
68
+ </div>
69
+ </div>
70
+ ))
71
+ ) : requests.length === 0 ? (
72
+ <div className="text-center py-8 text-gray-500">No maintenance requests</div>
73
+ ) : (
74
+ requests.slice(0, 5).map((request) => {
75
+ const issueType = request.Type__c?.value || "General";
76
+ const propertyAddress = request.Property__r?.Address__c?.value || "Unknown Address";
77
+ const description = request.Description__c?.value || "";
78
+ const tenantName = request.User__r?.Name?.value || "Unknown";
79
+
80
+ return (
81
+ <div
82
+ key={request.Id}
83
+ className="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
84
+ >
85
+ <div
86
+ className={`flex items-center justify-center w-12 h-12 ${issueIconColors[issueType] || "bg-purple-100"} rounded-lg flex-shrink-0`}
87
+ >
88
+ {issueIcons[issueType] ? (
89
+ <img src={issueIcons[issueType]} alt={issueType} className="w-6 h-6" />
90
+ ) : (
91
+ <span className="text-2xl">🔧</span>
92
+ )}
93
+ </div>
94
+
95
+ <div className="ml-4 w-64 flex-shrink-0">
96
+ <div className="flex items-center gap-2 mb-1">
97
+ <h3 className="font-semibold text-gray-900">{issueType}</h3>
98
+ <span className="text-gray-500">|</span>
99
+ <span className="text-sm text-gray-600 truncate">
100
+ {propertyAddress.split(",")[0]}
101
+ </span>
102
+ </div>
103
+ <p className="text-sm text-gray-500">
104
+ Request ID: {request.Id.substring(0, 8)}...
105
+ </p>
106
+ </div>
107
+
108
+ <div className="ml-4 w-80 flex-shrink-0">
109
+ <p className="text-sm text-gray-700 truncate">
110
+ {description || "No description"}
111
+ </p>
112
+ </div>
113
+
114
+ <div className="ml-4 w-48 flex-shrink-0 flex items-center gap-2">
115
+ <div className="w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center flex-shrink-0">
116
+ <span className="text-sm font-medium text-gray-700">
117
+ {tenantName.charAt(0) || "?"}
118
+ </span>
119
+ </div>
120
+ <span className="text-sm text-gray-700 font-medium truncate">{tenantName}</span>
121
+ </div>
122
+ </div>
123
+ );
124
+ })
125
+ )}
126
+ </div>
127
+ </Card>
128
+ );
129
+ };
@@ -0,0 +1,73 @@
1
+ import React from "react";
2
+ import { Card } from "../ui/card";
3
+ import { Skeleton } from "../ui/skeleton";
4
+ import upgraphIcon from "../../assets/icons/upgraph.svg";
5
+ import downgraphIcon from "../../assets/icons/downgraph.svg";
6
+ import { MoreVertical } from "lucide-react";
7
+
8
+ interface StatCardProps {
9
+ title: string;
10
+ value?: number | string;
11
+ trend?: {
12
+ value: number;
13
+ isPositive: boolean;
14
+ };
15
+ subtitle?: string;
16
+ loading?: boolean;
17
+ onClick?: () => void;
18
+ }
19
+
20
+ export const StatCard: React.FC<StatCardProps> = ({
21
+ title,
22
+ value,
23
+ trend,
24
+ subtitle,
25
+ loading,
26
+ onClick,
27
+ }) => {
28
+ return (
29
+ <Card
30
+ className={`p-4 border-gray-200 shadow-sm relative ${onClick ? "cursor-pointer hover:shadow-lg transition-shadow" : ""}`}
31
+ onClick={onClick}
32
+ >
33
+ {/* Three-dot menu */}
34
+ <button className="absolute top-4 right-4 p-1 hover:bg-gray-100 rounded-md transition-colors">
35
+ <MoreVertical className="w-4 h-4 text-gray-400" />
36
+ </button>
37
+
38
+ <div className="space-y-1">
39
+ <p className="text-sm font-medium text-gray-600 uppercase tracking-wide">{title}</p>
40
+ {loading ? (
41
+ <>
42
+ <div className="flex items-baseline gap-3">
43
+ <Skeleton className="h-9 w-11" />
44
+ <Skeleton className="h-6 w-14 rounded-full" />
45
+ </div>
46
+ <Skeleton className="h-5 w-30 mt-2" />
47
+ </>
48
+ ) : (
49
+ <>
50
+ <div className="flex items-baseline gap-3">
51
+ <p className="text-4xl font-bold text-primary-purple">{value}</p>
52
+ {trend && (
53
+ <span
54
+ className={`inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-sm font-medium ${
55
+ trend.isPositive ? "bg-cyan-100 text-cyan-800" : "bg-pink-100 text-pink-800"
56
+ }`}
57
+ >
58
+ <img
59
+ src={trend.isPositive ? upgraphIcon : downgraphIcon}
60
+ alt={trend.isPositive ? "Up" : "Down"}
61
+ className="w-4 h-4"
62
+ />
63
+ {Math.abs(trend.value)}%
64
+ </span>
65
+ )}
66
+ </div>
67
+ {subtitle && <p className="text-sm text-gray-500 mt-1">{subtitle}</p>}
68
+ </>
69
+ )}
70
+ </div>
71
+ </Card>
72
+ );
73
+ };
@@ -0,0 +1,23 @@
1
+ import { cn } from "../../lib/utils";
2
+
3
+ interface FilterRowProps extends React.ComponentProps<"div"> {
4
+ ariaLabel?: string;
5
+ }
6
+
7
+ export function FilterRow({
8
+ className,
9
+ ariaLabel = "Filters",
10
+ children,
11
+ ...props
12
+ }: FilterRowProps) {
13
+ return (
14
+ <div
15
+ className={cn("bg-white rounded-lg shadow-sm border border-gray-200 p-4 pb-2", className)}
16
+ role="region"
17
+ aria-label={ariaLabel}
18
+ {...props}
19
+ >
20
+ <div className="flex flex-wrap items-end gap-x-8 gap-y-4">{children}</div>
21
+ </div>
22
+ );
23
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ interface PageContainerProps {
4
+ children: ReactNode;
5
+ }
6
+
7
+ export function PageContainer({ children }: PageContainerProps) {
8
+ return (
9
+ <div className="min-h-screen bg-gray-50 p-4 md:p-8">
10
+ <div className="max-w-7xl mx-auto space-y-6">{children}</div>
11
+ </div>
12
+ );
13
+ }
@@ -0,0 +1,17 @@
1
+ interface PageHeaderProps {
2
+ title: string;
3
+ description: string;
4
+ }
5
+
6
+ /**
7
+ * Page title and optional description. Uses a consistent wrapper (max-w-7xl mx-auto px-8 pt-8)
8
+ * so the header aligns with list/content on all pages.
9
+ */
10
+ export function PageHeader({ title, description }: PageHeaderProps) {
11
+ return (
12
+ <div>
13
+ <h1 className="text-2xl font-bold text-gray-900">{title}</h1>
14
+ {description !== "" && <p className="text-gray-800 mt-1">{description}</p>}
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,55 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { ChevronDown, Menu } from "lucide-react";
3
+ import zenLogo from "../../assets/icons/zen-logo.svg";
4
+ import { getUserInfo } from "../../api/dashboard/dashboard";
5
+
6
+ interface TopBarProps {
7
+ onMenuClick?: () => void;
8
+ }
9
+
10
+ export const TopBar: React.FC<TopBarProps> = ({ onMenuClick }) => {
11
+ const [userName, setUserName] = useState<string>("User");
12
+
13
+ useEffect(() => {
14
+ const loadUserInfo = async () => {
15
+ const userInfo = await getUserInfo();
16
+ if (userInfo) {
17
+ setUserName(userInfo.name);
18
+ }
19
+ };
20
+ loadUserInfo();
21
+ }, []);
22
+ return (
23
+ <div className="bg-[#372949] text-white h-16 flex items-center justify-between px-6">
24
+ {/* Left section - Logo and Menu */}
25
+ <div className="flex items-center gap-4">
26
+ <button
27
+ onClick={onMenuClick}
28
+ className="p-2 hover:bg-purple-700 rounded-md transition-colors md:hidden"
29
+ aria-label="Toggle menu"
30
+ >
31
+ <Menu className="w-6 h-6" />
32
+ </button>
33
+ <div className="flex items-center gap-2">
34
+ <img src={zenLogo} alt="Zenlease Logo" className="w-8 h-8" />
35
+ <span className="text-xl tracking-wide">
36
+ <span className="font-light">ZEN</span>
37
+ <span className="font-semibold">LEASE</span>
38
+ </span>
39
+ </div>
40
+ </div>
41
+
42
+ {/* Right section - Profile */}
43
+ <div className="flex items-center gap-4">
44
+ {/* User Profile */}
45
+ <button className="flex items-center gap-2 px-3 py-2 hover:bg-purple-700 rounded-md transition-colors">
46
+ <div className="w-8 h-8 bg-purple-300 rounded-full flex items-center justify-center text-purple-900 font-semibold">
47
+ {userName.charAt(0).toUpperCase()}
48
+ </div>
49
+ <span className="hidden md:inline font-medium">{userName.toUpperCase()}</span>
50
+ <ChevronDown className="w-4 h-4 hidden md:inline" />
51
+ </button>
52
+ </div>
53
+ </div>
54
+ );
55
+ };