Skip to content

Commit 5b075ee

Browse files
committed
passed in email template, as well as roleID and applicationID, Rejection part unknown, now waitin for Azhad API
1 parent a333dda commit 5b075ee

File tree

3 files changed

+71
-33
lines changed

3 files changed

+71
-33
lines changed

backend/server/src/models/application.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -667,40 +667,46 @@ impl Application {
667667
a.status AS \"status: ApplicationStatus\", a.updated_at,
668668
669669
coalesce(
670-
to_jsonb(
671-
array_agg(
672-
jsonb_build_object(
673-
'id', ar.id,
674-
'rater_id', reviewer.id,
675-
'rater_name', reviewer.name,
676-
'comment', ar.comment,
677-
'category_ratings', (SELECT COALESCE(to_jsonb(array_agg(jsonb_build_object(
678-
'id', COALESCE(arc.id, 0),
679-
'campaign_rating_category_id', crc.id,
680-
'category_name', crc.name,
681-
'rating', arc.rating
682-
)
683-
)
684-
),'[]'::jsonb
685-
)
686-
FROM campaign_rating_categories crc
687-
LEFT JOIN application_rating_category_ratings arc
688-
ON arc.campaign_rating_category_id = crc.id
689-
AND arc.application_rating_id = ar.id
690-
WHERE crc.campaign_id = a.campaign_id
691-
),
692-
'updated_at', ar.updated_at
693-
) ORDER BY ar.updated_at DESC
694-
) FILTER (WHERE ar.id IS NOT NULL)
670+
(SELECT
671+
jsonb_agg(
672+
jsonb_build_object(
673+
'id', ar.id,
674+
'rater_id', reviewer.id,
675+
'rater_name', reviewer.name,
676+
'comment', ar.comment,
677+
'category_ratings', category_ratings_json,
678+
'updated_at', ar.updated_at
679+
) ORDER BY ar.updated_at DESC
680+
) FILTER (WHERE ar.id IS NOT NULL)
681+
FROM application_ratings ar
682+
JOIN users reviewer ON reviewer.id = ar.rater_id
683+
LEFT JOIN LATERAL (
684+
SELECT
685+
coalesce(
686+
jsonb_agg(
687+
jsonb_build_object(
688+
'id', COALESCE(arc.id, 0),
689+
'campaign_rating_category_id', crc.id,
690+
'category_name', crc.name,
691+
'rating', arc.rating
692+
) ORDER BY crc.id
693+
) FILTER (WHERE crc.id IS NOT NULL),
694+
'[]'::jsonb
695+
) as category_ratings_json
696+
FROM campaign_rating_categories crc
697+
LEFT JOIN application_rating_category_ratings arc
698+
ON arc.campaign_rating_category_id = crc.id
699+
AND arc.application_rating_id = ar.id
700+
WHERE crc.campaign_id = a.campaign_id
701+
) cat_ratings ON true
702+
WHERE ar.application_id = a.id
695703
),
696704
'[]'::jsonb
697705
) AS \"ratings!: Json<Vec<RatingDetails>>\"
698706
FROM applications a
699707
JOIN application_roles applied_roles ON applied_roles.application_id = a.id
700708
JOIN campaign_roles ON campaign_roles.id = applied_roles.campaign_role_id
701-
LEFT JOIN application_ratings ar ON ar.application_id = a.id
702709
JOIN users u ON u.id = a.user_id
703-
LEFT JOIN users AS reviewer ON reviewer.id = ar.rater_id
704710
WHERE a.campaign_id = $1 AND a.submitted = true
705711
GROUP BY a.id, u.name, u.email, a.status, a.updated_at
706712
ORDER BY a.id ASC

frontend-nextjs/src/app/[lang]/dashboard/organisation/[orgId]/campaigns/[campaignId]/applications/application-summary.tsx

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { dateToString } from "@/lib/utils";
55
import { ApplicationRatingSummary, getApplicationRatingsSummary} from "@/models/application";
66
import { getRatingCategories, RatingDetails } from "@/models/rating"
77
import { getCampaign, getCampaignRoles } from "@/models/campaign";
8+
import { getOrganisationEmailTemplates } from "@/models/email";
89
import { useQuery } from "@tanstack/react-query";
910
import { ArrowLeft, MoreHorizontal } from "lucide-react";
1011
import Link from "next/link";
@@ -225,6 +226,27 @@ export default function ApplicationSummary({ campaignId, orgId, dict }: { campai
225226
queryFn: () => getRatingCategories(campaignId),
226227
});
227228

229+
const { data: emailTemplates } = useQuery({
230+
queryKey: [`${orgId}-email-templates`],
231+
queryFn: () => getOrganisationEmailTemplates(orgId),
232+
});
233+
234+
// Current way to differentiate an email template of "Offer"
235+
// No Reject yet
236+
// Could also make use of "Interview status"
237+
const offerTemplate = useMemo(() => {
238+
const template = emailTemplates?.find(template =>
239+
template.name.toLowerCase().includes("offer")
240+
);
241+
242+
// Validation of email template organisation_id matches the campaign organisation_id
243+
if (template && campaign && template.organisation_id !== campaign.organisation_id) {
244+
console.error('Email template organisation_id does not match campaign organisation_id');
245+
return undefined;
246+
}
247+
248+
return template;
249+
}, [emailTemplates, campaign]);
228250
const handleAccept = useCallback((applicationId: string, appliedRoles: string[]) => {
229251
// If already accepted, we can undo the acception
230252
if (acceptedApplicationIds.has(applicationId)) {
@@ -250,8 +272,12 @@ export default function ApplicationSummary({ campaignId, orgId, dict }: { campai
250272
} else {
251273
// Single role applied, no popup needed - store the role ID
252274
setAcceptedApplications(prev => new Map(prev).set(applicationId, appliedRoles[0]));
275+
276+
if (offerTemplate) {
277+
console.log(`Accepted application ${applicationId} with role ${appliedRoles[0]} and email template ${offerTemplate.id} (${offerTemplate.name})`);
278+
}
253279
}
254-
}, [acceptedApplicationIds]);
280+
}, [acceptedApplicationIds, offerTemplate]);
255281

256282
const handleReject = useCallback((applicationId: string) => {
257283
// If already rejected, we can undo the rejection
@@ -278,16 +304,18 @@ export default function ApplicationSummary({ campaignId, orgId, dict }: { campai
278304
newSet.add(applicationId);
279305
return newSet;
280306
});
281-
console.log(`Rejected application ${applicationId}`);
282307
}, [rejectedApplicationIds, acceptedApplications]);
283308

284309
const handleRoleConfirm = useCallback((selectedRoleId: string) => {
285310
if (currentApplication) {
286311
// Store the selected role ID along with the application ID
287312
setAcceptedApplications(prev => new Map(prev).set(currentApplication.id, selectedRoleId));
288-
console.log(`Selected role ${selectedRoleId} for application ${currentApplication.id}`);
313+
314+
if (offerTemplate) {
315+
console.log(`Accepted application ${currentApplication.id} with role ${selectedRoleId} and email template ${offerTemplate.id} (${offerTemplate.name})`);
316+
}
289317
}
290-
}, [currentApplication]);
318+
}, [currentApplication, offerTemplate]);
291319

292320
return (
293321
<div>
@@ -313,6 +341,7 @@ export default function ApplicationSummary({ campaignId, orgId, dict }: { campai
313341
acceptedApplicationIds={acceptedApplicationIds}
314342
acceptedApplications={acceptedApplications}
315343
rejectedApplicationIds={rejectedApplicationIds}
344+
offerTemplateId={offerTemplate?.id}
316345
renderSubComponent={({ row }) => <RatingsShelf columns={getColumns(dict, roleIdsToNames, ratingCategories ?? [], handleAccept, handleReject, acceptedApplicationIds, rejectedApplicationIds, ActionsCell)} ratings={row.original.ratings} applicationId={row.original.application_id} dict={dict} />}
317346
/>
318347
</div>

frontend-nextjs/src/app/[lang]/dashboard/organisation/[orgId]/campaigns/[campaignId]/applications/data-table.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface DataTableProps<TData, TValue> {
4141
acceptedApplicationIds: Set<string>;
4242
acceptedApplications: Map<string, string>; // Map of applicationId -> selectedRoleId
4343
rejectedApplicationIds: Set<string>;
44+
offerTemplateId?: string;
4445
renderSubComponent?: (props: { row: Row<TData> }) => React.ReactNode;
4546
}
4647

@@ -52,6 +53,7 @@ export function ApplicationSummaryDataTable<TData, TValue>({
5253
acceptedApplicationIds,
5354
acceptedApplications,
5455
rejectedApplicationIds,
56+
offerTemplateId,
5557
renderSubComponent,
5658
}: DataTableProps<TData, TValue>) {
5759
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
@@ -90,11 +92,12 @@ export function ApplicationSummaryDataTable<TData, TValue>({
9092
const rejectionData = Array.from(rejectedApplicationIds);
9193

9294
if (acceptanceData.length > 0) {
93-
console.log("Sent Acceptance Email to applicationIDs:", acceptanceData);
95+
const offerEmailPart = offerTemplateId ? `[EmailTemplate: ${offerTemplateId}] ` : '';
96+
console.log(`Sent Acceptance Email ${offerEmailPart}to ApplicationIDs:`, acceptanceData);
9497
}
9598

9699
if (rejectionData.length > 0) {
97-
console.log("Sent Rejection Email to ApplicationIDs:", rejectionData);
100+
console.log(`Sent Rejection Email to ApplicationIDs:`, rejectionData);
98101
}
99102
};
100103

0 commit comments

Comments
 (0)