@salesforce/webapp-template-app-react-sample-b2e-experimental 1.116.9 → 1.116.11

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 (18) hide show
  1. package/dist/CHANGELOG.md +16 -0
  2. package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler.cls +9 -6
  3. package/dist/force-app/main/default/classes/TenantTriggerHandler.cls +8 -0
  4. package/dist/force-app/main/default/classes/TenantTriggerHandler_Test.cls +4 -0
  5. package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Type__c.field-meta.xml +20 -0
  6. package/dist/force-app/main/default/webapplications/propertymanagementapp/package.json +4 -4
  7. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/api/applications/applications.ts +69 -2
  8. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/api/applications/query/applicationForApproval.graphql +22 -0
  9. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/api/applications/query/existingTenant.graphql +16 -0
  10. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/api/applications/query/userByContact.graphql +13 -0
  11. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/api/graphql-operations-types.ts +6706 -2317
  12. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/components/AgentforceConversationClient.tsx +5 -2
  13. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/pages/ApplicationSearch.tsx +7 -3
  14. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/pages/MaintenanceRequestSearch.tsx +7 -3
  15. package/dist/force-app/main/default/webapplications/propertymanagementapp/src/types/conversation.ts +2 -0
  16. package/dist/package-lock.json +2 -2
  17. package/dist/package.json +1 -1
  18. package/package.json +2 -2
package/dist/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.116.11](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.116.10...v1.116.11) (2026-03-27)
7
+
8
+ **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
9
+
10
+
11
+
12
+
13
+
14
+ ## [1.116.10](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.116.9...v1.116.10) (2026-03-27)
15
+
16
+ **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
17
+
18
+
19
+
20
+
21
+
6
22
  ## [1.116.9](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.116.8...v1.116.9) (2026-03-27)
7
23
 
8
24
  **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
@@ -1,4 +1,4 @@
1
- public with sharing class MaintenanceRequestTriggerHandler {
1
+ public without sharing class MaintenanceRequestTriggerHandler {
2
2
 
3
3
  /**
4
4
  * Handles before insert logic for Maintenance Request records
@@ -7,11 +7,14 @@ public with sharing class MaintenanceRequestTriggerHandler {
7
7
  public static void handleBeforeInsert(List<Maintenance_Request__c> newRequests) {
8
8
  // Map to store request type to worker type mappings
9
9
  Map<String, String> requestTypeToWorkerType = new Map<String, String>{
10
- 'Plumbing' => 'Plumbing',
11
- 'Electrical' => 'Electrical',
12
- 'HVAC' => 'HVAC (Heating & Cooling)',
13
- 'Appliance' => 'Appliance Repair',
14
- 'Pest' => 'Pest Control'
10
+ 'Plumbing' => 'Plumbing',
11
+ 'Electrical' => 'Electrical',
12
+ 'HVAC' => 'HVAC (Heating & Cooling)',
13
+ 'Appliance' => 'Appliance Repair',
14
+ 'Carpentry' => 'General Carpentry',
15
+ 'Landscaping' => 'Landscaping / Grounds',
16
+ 'Cleaning' => 'Janitorial / Cleaning',
17
+ 'Pest' => 'Pest Control'
15
18
  };
16
19
 
17
20
  // Collect unique worker types needed
@@ -29,7 +29,15 @@ public with sharing class TenantTriggerHandler {
29
29
  if (userIds.isEmpty()) {
30
30
  return;
31
31
  }
32
+ assignTenantMaintenanceAccessAsync(new List<Id>(userIds));
33
+ }
32
34
 
35
+ @future
36
+ private static void assignTenantMaintenanceAccessAsync(List<Id> userIdsList) {
37
+ Set<Id> userIds = new Set<Id>(userIdsList);
38
+ if (userIds.isEmpty()) {
39
+ return;
40
+ }
33
41
  List<PermissionSet> permSets = [
34
42
  SELECT Id
35
43
  FROM PermissionSet
@@ -73,7 +73,9 @@ private class TenantTriggerHandler_Test {
73
73
  static void testNoDuplicateAssign() {
74
74
  Id runAsUserId = UserInfo.getUserId();
75
75
  Tenant__c tenant = new Tenant__c(User__c = runAsUserId);
76
+ Test.startTest();
76
77
  insert tenant;
78
+ Test.stopTest();
77
79
 
78
80
  Integer countBefore = [
79
81
  SELECT COUNT()
@@ -82,8 +84,10 @@ private class TenantTriggerHandler_Test {
82
84
  AND PermissionSet.Name = 'Tenant_Maintenance_Access'
83
85
  ];
84
86
 
87
+ Test.startTest();
85
88
  tenant.Status__c = 'Active';
86
89
  update tenant;
90
+ Test.stopTest();
87
91
 
88
92
  Integer countAfter = [
89
93
  SELECT COUNT()
@@ -32,11 +32,31 @@
32
32
  <default>false</default>
33
33
  <label>Appliance</label>
34
34
  </value>
35
+ <value>
36
+ <fullName>Carpentry</fullName>
37
+ <default>false</default>
38
+ <label>Carpentry</label>
39
+ </value>
40
+ <value>
41
+ <fullName>Landscaping</fullName>
42
+ <default>false</default>
43
+ <label>Landscaping</label>
44
+ </value>
45
+ <value>
46
+ <fullName>Cleaning</fullName>
47
+ <default>false</default>
48
+ <label>Cleaning</label>
49
+ </value>
35
50
  <value>
36
51
  <fullName>Pest</fullName>
37
52
  <default>false</default>
38
53
  <label>Pest Control</label>
39
54
  </value>
55
+ <value>
56
+ <fullName>Other</fullName>
57
+ <default>false</default>
58
+ <label>Other</label>
59
+ </value>
40
60
  </valueSetDefinition>
41
61
  </valueSet>
42
62
  </CustomField>
@@ -15,8 +15,8 @@
15
15
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
16
16
  },
17
17
  "dependencies": {
18
- "@salesforce/sdk-data": "^1.116.9",
19
- "@salesforce/webapp-experimental": "^1.116.9",
18
+ "@salesforce/sdk-data": "^1.116.11",
19
+ "@salesforce/webapp-experimental": "^1.116.11",
20
20
  "@tailwindcss/vite": "^4.1.17",
21
21
  "class-variance-authority": "^0.7.1",
22
22
  "clsx": "^2.1.1",
@@ -32,7 +32,7 @@
32
32
  "tailwind-merge": "^3.5.0",
33
33
  "tailwindcss": "^4.1.17",
34
34
  "tw-animate-css": "^1.4.0",
35
- "@salesforce/agentforce-conversation-client": "^1.102.0",
35
+ "@salesforce/agentforce-conversation-client": "^1.116.9",
36
36
  "recharts": "^2.15.0"
37
37
  },
38
38
  "devDependencies": {
@@ -43,7 +43,7 @@
43
43
  "@graphql-eslint/eslint-plugin": "^4.1.0",
44
44
  "@graphql-tools/utils": "^11.0.0",
45
45
  "@playwright/test": "^1.49.0",
46
- "@salesforce/vite-plugin-webapp-experimental": "^1.116.9",
46
+ "@salesforce/vite-plugin-webapp-experimental": "^1.116.11",
47
47
  "@testing-library/jest-dom": "^6.6.3",
48
48
  "@testing-library/react": "^16.1.0",
49
49
  "@testing-library/user-event": "^14.5.2",
@@ -1,10 +1,20 @@
1
1
  import GET_APPLICATIONS from "./query/getApplications.graphql?raw";
2
2
  import UPDATE_APPLICATION_STATUS from "./query/updateApplicationStatus.graphql?raw";
3
+ import APPLICATION_FOR_APPROVAL_QUERY from "./query/applicationForApproval.graphql?raw";
4
+ import USER_BY_CONTACT_QUERY from "./query/userByContact.graphql?raw";
5
+ import EXISTING_TENANT_QUERY from "./query/existingTenant.graphql?raw";
6
+ import { createRecord } from "@salesforce/webapp-experimental/api";
3
7
  import type {
4
8
  GetApplicationsQuery,
5
- UpdateApplicationStatusMutationVariables,
6
- UpdateApplicationStatusMutation,
7
9
  GetApplicationsQueryVariables,
10
+ UpdateApplicationStatusMutation,
11
+ UpdateApplicationStatusMutationVariables,
12
+ ApplicationForApprovalQuery,
13
+ ApplicationForApprovalQueryVariables,
14
+ UserByContactQuery,
15
+ UserByContactQueryVariables,
16
+ ExistingTenantQuery,
17
+ ExistingTenantQueryVariables,
8
18
  } from "../graphql-operations-types.js";
9
19
  import { executeGraphQL } from "../graphqlClient.js";
10
20
 
@@ -14,6 +24,8 @@ export type ApplicationNode = NonNullable<
14
24
  >[number]
15
25
  >["node"];
16
26
 
27
+ const TENANT_OBJECT_API_NAME = "Tenant__c";
28
+
17
29
  export async function getApplications(): Promise<NonNullable<ApplicationNode>[]> {
18
30
  try {
19
31
  const data = await executeGraphQL<GetApplicationsQuery, GetApplicationsQueryVariables>(
@@ -34,6 +46,11 @@ export async function updateApplicationStatus(
34
46
  applicationId: string,
35
47
  status: string,
36
48
  ): Promise<boolean> {
49
+ const normalizedStatus = status.trim().toLowerCase();
50
+ if (normalizedStatus === "approved") {
51
+ await ensureTenantForApprovedApplication(applicationId);
52
+ }
53
+
37
54
  const variables: UpdateApplicationStatusMutationVariables = {
38
55
  input: {
39
56
  Id: applicationId,
@@ -53,3 +70,53 @@ export async function updateApplicationStatus(
53
70
  return false;
54
71
  }
55
72
  }
73
+
74
+ async function ensureTenantForApprovedApplication(applicationId: string): Promise<void> {
75
+ const appData = await executeGraphQL<
76
+ ApplicationForApprovalQuery,
77
+ ApplicationForApprovalQueryVariables
78
+ >(APPLICATION_FOR_APPROVAL_QUERY, { applicationId });
79
+ const applicationNode = appData.uiapi?.query?.Application__c?.edges?.[0]?.node;
80
+ if (!applicationNode) {
81
+ throw new Error("Application record not found.");
82
+ }
83
+
84
+ const contactId = applicationNode.User__c?.value ?? null;
85
+ const propertyId = applicationNode.Property__c?.value ?? null;
86
+ const startDate = applicationNode.Start_Date__c?.value ?? null;
87
+
88
+ if (!contactId || !propertyId) {
89
+ return;
90
+ }
91
+
92
+ const userData = await executeGraphQL<UserByContactQuery, UserByContactQueryVariables>(
93
+ USER_BY_CONTACT_QUERY,
94
+ { contactId },
95
+ );
96
+ const userId = userData.uiapi?.query?.User?.edges?.[0]?.node?.Id ?? null;
97
+ if (!userId) {
98
+ return;
99
+ }
100
+
101
+ const existingTenantData = await executeGraphQL<
102
+ ExistingTenantQuery,
103
+ ExistingTenantQueryVariables
104
+ >(EXISTING_TENANT_QUERY, {
105
+ userId,
106
+ propertyId,
107
+ });
108
+ const existingTenantId = existingTenantData.uiapi?.query?.Tenant__c?.edges?.[0]?.node?.Id ?? null;
109
+ if (existingTenantId) return;
110
+
111
+ const tenantFields: Record<string, unknown> = {
112
+ User__c: userId,
113
+ Property__c: propertyId,
114
+ User_Status__c: "Tenant",
115
+ Status__c: "Active",
116
+ };
117
+ if (startDate) {
118
+ tenantFields.Start_Date__c = String(startDate);
119
+ }
120
+
121
+ await createRecord(TENANT_OBJECT_API_NAME, tenantFields);
122
+ }
@@ -0,0 +1,22 @@
1
+ query ApplicationForApproval($applicationId: ID!) {
2
+ uiapi {
3
+ query {
4
+ Application__c(where: { Id: { eq: $applicationId } }, first: 1) {
5
+ edges {
6
+ node {
7
+ Id
8
+ User__c @optional {
9
+ value
10
+ }
11
+ Property__c @optional {
12
+ value
13
+ }
14
+ Start_Date__c @optional {
15
+ value
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ query ExistingTenant($userId: ID!, $propertyId: ID!) {
2
+ uiapi {
3
+ query {
4
+ Tenant__c(
5
+ where: { and: [{ User__c: { eq: $userId } }, { Property__c: { eq: $propertyId } }] }
6
+ first: 1
7
+ ) {
8
+ edges {
9
+ node {
10
+ Id
11
+ }
12
+ }
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,13 @@
1
+ query UserByContact($contactId: ID!) {
2
+ uiapi {
3
+ query {
4
+ User(where: { ContactId: { eq: $contactId } }, first: 1) {
5
+ edges {
6
+ node {
7
+ Id
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }