Skip to content

Commit bd2244a

Browse files
committed
refactor: add type helpers and build new type paradigm
Update ActivityContact, Permit, and Note types
1 parent 28e1fdd commit bd2244a

29 files changed

Lines changed: 401 additions & 285 deletions

frontend/src/components/authorization/AuthorizationForm.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { notInFutureValidator } from '@/validators/common';
2424
import type { Ref } from 'vue';
2525
import type { Permit, PermitTracking, PermitType, SourceSystemKind, User } from '@/types';
2626
import type { IStamps } from '@/interfaces';
27-
import type { PermitArgs } from '@/types/Permit';
27+
import type { PermitUpsertArgs } from '@/types/models';
2828
2929
// Props
3030
const { authorization = undefined, editable } = defineProps<{
@@ -269,7 +269,8 @@ function onDelete() {
269269
rejectProps: { outlined: true },
270270
accept: async () => {
271271
try {
272-
await permitService.deletePermit(authorization?.permitId as string);
272+
if (!authorization) throw new Error('No authorization');
273+
await permitService.deletePermit({ permitId: authorization.permitId });
273274
toast.success(t('authorization.authorizationForm.authDeleted'));
274275
if (!projectRouteName?.value) throw new Error('No route');
275276
router.push({
@@ -300,7 +301,7 @@ async function onSubmit(data: GenericObject) {
300301
const statusLastVerified = splitDateTime(data.statusLastVerified);
301302
302303
const { authorizationType, permitNote, ...rest } = data as FormSchemaType;
303-
const permitData: PermitArgs = {
304+
const permitData: PermitUpsertArgs = {
304305
...rest,
305306
activityId: getProject.value!.activityId,
306307
permitTypeId: authorizationType.permitTypeId,

frontend/src/components/enquiry/EnquiryForm.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,11 @@ const onSubmit = async (values: GenericObject) => {
302302
if (primaryContact.value?.contactId !== values.contact.contactId) {
303303
const newContact = (await contactService.updateContact(values.contact)).data;
304304
if (newContact.contactId) {
305-
await activityContactService.createActivityContact(
306-
enquiry.activityId,
307-
newContact.contactId,
308-
ActivityContactRole.PRIMARY
309-
);
305+
await activityContactService.createActivityContact({
306+
activityId: enquiry.activityId,
307+
contactId: newContact.contactId,
308+
role: ActivityContactRole.PRIMARY
309+
});
310310
311311
setBasicInfo(newContact);
312312
}

frontend/src/components/projectCommon/ProjectTeamTab.vue

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ async function onAddUsers(contactsAndRoles: { contact: Contact; role: ActivityCo
124124
if (!getProject.value?.activityId) throw new Error('No activity ID');
125125
126126
const response = (
127-
await activityContactService.createActivityContact(getProject.value.activityId, contact.contactId, role)
127+
await activityContactService.createActivityContact({
128+
activityId: getProject.value.activityId,
129+
contactId: contact.contactId,
130+
role
131+
})
128132
).data;
129133
130134
// Update store
@@ -162,7 +166,11 @@ async function onManageUser(contact: ActivityContact, role: ActivityContactRole)
162166
if (!getProject.value?.activityId) throw new Error('No activity ID');
163167
164168
const { updated, demoted } = (
165-
await activityContactService.updateActivityContact(getProject.value.activityId, contact.contactId, role)
169+
await activityContactService.updateActivityContact({
170+
activityId: getProject.value.activityId,
171+
contactId: contact.contactId,
172+
role
173+
})
166174
).data;
167175
168176
// Update store
@@ -212,7 +220,10 @@ async function onRevokeUser(contact: ActivityContact) {
212220
try {
213221
if (!getProject.value?.activityId) throw new Error('No activity ID');
214222
215-
await activityContactService.deleteActivityContact(getProject.value.activityId, contact.contactId);
223+
await activityContactService.deleteActivityContact({
224+
activityId: getProject.value.activityId,
225+
contactId: contact.contactId
226+
});
216227
217228
// Update store
218229
projectStore.removeActivityContact(contact);

frontend/src/interfaces/IProject.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { IStamps } from '@/interfaces';
2-
import type { Activity } from '@/types/Activity';
2+
import type { Activity } from '@/types/models';
33
import type { Contact } from '@/types/Contact';
44
import type { User } from '@/types/User';
55
import type { ApplicationStatus, SubmissionType } from '@/utils/enums/projectCommon';

frontend/src/services/activityContactService.ts

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,59 @@ import { appAxios } from './interceptors';
22

33
import type { AxiosResponse } from 'axios';
44
import type { ActivityContact } from '@/types';
5+
import type {
6+
ActivityContactCreateArgs,
7+
ActivityContactDeleteArgs,
8+
ActivityContactUpdateArgs
9+
} from '@/types/ActivityContact';
510

6-
export default {
7-
/**
8-
* @function listActivityContacts
9-
* @returns {Promise} An axios response
10-
*/
11-
createActivityContact(activityId: string, contactId: string, role: string): Promise<AxiosResponse<ActivityContact>> {
12-
return appAxios().post(`activity/${activityId}/contact/${contactId}`, { role });
13-
},
11+
/**
12+
* Create an Activity Contact
13+
* @param args - DTO containing path params and fields
14+
* @returns Axios response with the created ActivityContact
15+
*/
16+
export function createActivityContact(args: ActivityContactCreateArgs): Promise<AxiosResponse<ActivityContact>> {
17+
const { activityId, contactId, ...body } = args;
18+
return appAxios().post(`activity/${activityId}/contact/${contactId}`, body);
19+
}
1420

15-
/**
16-
* @function deleteActivityContacts
17-
* @returns {Promise} An axios response
18-
*/
19-
deleteActivityContact(activityId: string, contactId: string): Promise<AxiosResponse<ActivityContact>> {
20-
return appAxios().delete(`activity/${activityId}/contact/${contactId}`);
21-
},
21+
/**
22+
* Delete an Activity Contact
23+
* @param args - DTO containing the compound key for deletion
24+
* @returns Axios response with the deleted ActivityContact
25+
*/
26+
export function deleteActivityContact(args: ActivityContactDeleteArgs): Promise<AxiosResponse<ActivityContact>> {
27+
const { activityId, contactId } = args;
28+
return appAxios().delete(`activity/${activityId}/contact/${contactId}`);
29+
}
2230

23-
/**
24-
* @function listActivityContacts
25-
* @returns {Promise} An axios response
26-
*/
27-
listActivityContacts(activityId: string): Promise<AxiosResponse<ActivityContact[]>> {
28-
return appAxios().get(`activity/${activityId}/contact`);
29-
},
31+
/**
32+
* List Activity Contact for a specific activity
33+
* @param activityId - ID of the activity to list contacts for
34+
* @returns Axios response with an array of ActivityContacts
35+
*/
36+
export function listActivityContacts(activityId: string): Promise<AxiosResponse<ActivityContact[]>> {
37+
return appAxios().get(`activity/${activityId}/contact`);
38+
}
3039

31-
/**
32-
* @function updateActivityContact
33-
* @returns {Promise} An axios response
34-
*/
35-
updateActivityContact(
36-
activityId: string,
37-
contactId: string,
38-
role: string
39-
): Promise<AxiosResponse<{ updated: ActivityContact; demoted: ActivityContact | undefined }>> {
40-
return appAxios().put(`activity/${activityId}/contact/${contactId}`, { role });
41-
}
40+
/**
41+
* Update an Activity Contact
42+
* @param args - DTO containing path params and updatable fields
43+
* @returns Axios response containing updated and optionally demoted ActivityContact
44+
*/
45+
export function updateActivityContact(
46+
args: ActivityContactUpdateArgs
47+
): Promise<AxiosResponse<{ updated: ActivityContact; demoted: ActivityContact | undefined }>> {
48+
const { activityId, contactId, ...body } = args;
49+
return appAxios().put(`activity/${activityId}/contact/${contactId}`, body);
50+
}
51+
52+
/** Hybrid default export object for backward compatibility */
53+
const activityService = {
54+
createActivityContact,
55+
updateActivityContact,
56+
deleteActivityContact,
57+
listActivityContacts
4258
};
59+
60+
export default activityService;
Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,72 @@
11
import { appAxios } from './interceptors';
22
import { useAppStore } from '@/store';
33

4-
import type { ListPermitsOptions, Permit } from '@/types';
5-
import type { Initiative } from '@/utils/enums/application';
4+
import type { AxiosResponse } from 'axios';
5+
import type { ListPermitsOptions, Permit, PermitType } from '@/types';
6+
import type { PermitDeleteArgs, PermitUpsertArgs } from '@/types/models';
67

78
const PATH = 'permit';
89

9-
export default {
10-
/**
11-
* @function deletePermit
12-
* @returns {Promise} An axios response
13-
*/
14-
deletePermit(permitId: string) {
15-
return appAxios().delete(`${useAppStore().getInitiative.toLowerCase()}/${PATH}/${permitId}`);
16-
},
17-
18-
/**
19-
* @function getPermit
20-
* @returns {Promise} An axios response
21-
*/
22-
getPermit(permitId: string) {
23-
return appAxios().get(`${useAppStore().getInitiative.toLowerCase()}/${PATH}/${permitId}`);
24-
},
25-
26-
/**
27-
* @function getPermitTypes
28-
* @param {Initiative} initiative Initiative type to get permit types for
29-
* @returns {Promise} An axios response
30-
*/
31-
getPermitTypes(initiative: Initiative) {
32-
return appAxios().get(`${useAppStore().getInitiative.toLowerCase()}/${PATH}/types`, { params: { initiative } });
33-
},
34-
35-
/**
36-
* @function listPermits
37-
* @returns {Promise} An axios response
38-
*/
39-
async listPermits(options?: ListPermitsOptions) {
40-
return appAxios().get(`${useAppStore().getInitiative.toLowerCase()}/${PATH}`, { params: options });
41-
},
42-
43-
/**
44-
* @function upsertPermit
45-
* @returns {Promise} An axios response
46-
*/
47-
upsertPermit(data: Permit) {
48-
return appAxios().put(`${useAppStore().getInitiative.toLowerCase()}/${PATH}`, data);
49-
}
10+
/** Helper to get initiative-prefixed base URL */
11+
function getBaseUrl(): string {
12+
return `${useAppStore().getInitiative.toLowerCase()}/${PATH}`;
13+
}
14+
15+
/**
16+
* Delete a Permit
17+
* @param data - DTO containing permitId
18+
* @returns Axios response with the deleted Permit
19+
*/
20+
export function deletePermit(data: PermitDeleteArgs): Promise<AxiosResponse<Permit>> {
21+
const { permitId } = data;
22+
return appAxios().delete(`${getBaseUrl()}/${permitId}`);
23+
}
24+
25+
/**
26+
* Get a single Permit by ID
27+
* @param permitId - ID of the permit to fetch
28+
* @returns Axios response with the Permit
29+
*/
30+
export function getPermit(permitId: string): Promise<AxiosResponse<Permit>> {
31+
return appAxios().get(`${getBaseUrl()}/${permitId}`);
32+
}
33+
34+
/**
35+
* Get Permit types for a given initiative
36+
* @param initiative - Initiative type
37+
* @returns Axios response with permit types
38+
*/
39+
export function getPermitTypes(initiative: string): Promise<AxiosResponse<PermitType[]>> {
40+
return appAxios().get(`${useAppStore().getInitiative.toLowerCase()}/${PATH}/types`, {
41+
params: { initiative }
42+
});
43+
}
44+
45+
/**
46+
* List Permits with optional filters
47+
* @param options - Optional query parameters for listing
48+
* @returns Axios response with an array of Permits
49+
*/
50+
export function listPermits(options?: ListPermitsOptions): Promise<AxiosResponse<Permit[]>> {
51+
return appAxios().get(getBaseUrl(), { params: options });
52+
}
53+
54+
/**
55+
* Upsert (create or update) a Permit
56+
* @param data - Full Permit object
57+
* @returns Axios response with the upserted Permit
58+
*/
59+
export function upsertPermit(data: PermitUpsertArgs): Promise<AxiosResponse<Permit>> {
60+
return appAxios().put(getBaseUrl(), data);
61+
}
62+
63+
/** Hybrid default export object for backward compatibility */
64+
const permitService = {
65+
upsertPermit,
66+
deletePermit,
67+
getPermit,
68+
listPermits,
69+
getPermitTypes
5070
};
71+
72+
export default permitService;

frontend/src/types/Activity.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import type { IStamps } from '@/interfaces';
22
import type { Contact } from '@/types';
33
import type { ActivityContactRole } from '@/utils/enums/projectCommon';
4+
import type { CreateDTO, DeleteDTO, PutDTO } from './helpers';
45

5-
export type ActivityContact = {
6+
export interface ActivityContact extends IStamps {
67
activityId: string;
78
contactId: string;
89
role: ActivityContactRole;
9-
10-
// Joined
1110
contact?: Contact;
12-
} & Partial<IStamps>;
11+
}
12+
13+
type ActivityContactExcludedKeys = 'contact';
14+
15+
export type ActivityContactCreateArgs = CreateDTO<ActivityContact, ActivityContactExcludedKeys>;
16+
export type ActivityContactDeleteArgs = DeleteDTO<ActivityContact, ['activityId', 'contactId']>;
17+
export type ActivityContactUpdateArgs = PutDTO<ActivityContact, ActivityContactExcludedKeys>;

frontend/src/types/DeepPartial.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

frontend/src/types/ElectrificationProjectIntake.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)