Skip to main content

Therapist Management

Therapist Management provides comprehensive therapist profile management, approval workflows, and child assignment capabilities. This system handles therapist lifecycle management with critical business logic for verification, specialization matching, and performance tracking.

Core Concepts

  • Approval Workflow: Pending, approved, and rejected therapist statuses
  • Specialization Management: Therapist specializations and skill matching
  • Document Verification: Upload and verify professional documents
  • Child Assignment: Assign therapists to children based on specialization
  • Performance Tracking: Monitor therapist performance and client satisfaction

Web/Admin Capabilities

1) List & Filter by Status

Business Rules:

  • Status Tabs: All therapists and Pending approval tabs
  • Filter Options: Filter by gender, approval status, activity status, and specialization
  • Search Capabilities: Search by name, unique code, or therapist ID
  • Sorting: Sort by name, contact, experience, and other fields
  • Approval Management: Handle pending therapist approvals and rejections

Implementation:

// Status-based tab organization
enum TherapistListingTabs {
all,
pending,
}

const validTab = useCallback(
(
currentTab: string | undefined | null,
): keyof typeof TherapistListingTabs => {
if (currentTab) {
const validCurrentTab =
Object.keys(TherapistListingTabs).includes(currentTab);
if (validCurrentTab) {
return currentTab as keyof typeof TherapistListingTabs;
} else {
return TherapistListingTabs[0] as keyof typeof TherapistListingTabs;
}
} else {
return TherapistListingTabs[0] as keyof typeof TherapistListingTabs;
}
},
[],
);

// Search implementation with UUID detection
const search: Therapist_Bool_Exp = isUUID(searchString)
? {
_or: [
{ user: { name: { _ilike: `%${searchString}%` } } },
{ id: { _eq: searchString } },
{ unique_code: { _ilike: `%${searchString}%` } },
],
}
: {
_or: [
{ user: { name: { _ilike: `%${searchString}%` } } },
{ unique_code: { _ilike: `%${searchString}%` } },
],
};

2) Therapist Profile Management

Therapist Management Business Rules:

  • Profile Creation: Create new therapist profiles with professional details
  • Document Upload: Upload and verify professional documents
  • Specialization Assignment: Assign relevant specializations to therapists
  • Approval Workflow: Review and approve/reject therapist applications
  • Status Management: Manage therapist active/inactive status

Therapist Profile Logic:

// Therapist profile validation
const validateTherapistProfile = (therapist: TherapistInput) => {
const errors: string[] = [];

if (!therapist.user_id) {
errors.push('User association is required');
}

if (!therapist.specializations || therapist.specializations.length === 0) {
errors.push('At least one specialization is required');
}

if (!therapist.experience_years || therapist.experience_years < 0) {
errors.push('Valid experience years is required');
}

if (!therapist.qualification) {
errors.push('Qualification is required');
}

return errors;
};

// Document verification workflow
const verifyDocuments = (therapistId: string, documents: DocumentInput[]) => {
return updateTherapistMutation({
variables: {
therapist_id: therapistId,
documents: documents,
verification_status: 'VERIFIED',
},
});
};

GraphQL Implementation:

import { gql, ApolloClient } from '@apollo/client';

const GET_THERAPIST_LIST = gql`
query GetTherapistList(
$limit: Int
$offset: Int
$where: therapist_bool_exp
$order_by: [therapist_order_by!]
) {
therapists(
limit: $limit
offset: $offset
where: $where
order_by: $order_by
) {
id
unique_code
experience_years
qualification
approval_status
status
created_at
user {
id
name
email
phone
gender
last_active
}
therapist_specialities {
speciality {
id
title
}
}
documents {
id
document_type
file_url
verification_status
}
}
therapists_aggregate(where: $where) {
aggregate {
count
}
}
}
`;

const DELETE_THERAPISTS = gql`
mutation DeleteTherapists($therapist_ids: [uuid!]!) {
deleteTherapists(therapist_ids: $therapist_ids) {
success
message
}
}
`;

const UPDATE_THERAPIST_STATUS = gql`
mutation UpdateTherapistStatus(
$therapist_id: uuid!
$approval_status: approval_status_enum!
) {
update_therapist(
where: { id: { _eq: $therapist_id } }
_set: { approval_status: $approval_status }
) {
affected_rows
}
}
`;

const ASSIGN_CHILD_TO_THERAPIST = gql`
mutation AssignChildToTherapist($therapist_id: uuid!, $child_id: uuid!) {
insert_therapist_child_assignment(
objects: { therapist_id: $therapist_id, child_id: $child_id }
) {
affected_rows
}
}
`;

async function getTherapistList(
client: ApolloClient<unknown>,
variables: {
limit: number;
offset: number;
where?: Therapist_Bool_Exp;
order_by?: Therapist_Order_By[];
},
) {
const { data } = await client.query({
query: GET_THERAPIST_LIST,
variables,
fetchPolicy: 'cache-and-network',
});

return {
therapists: data.therapists,
totalCount: data.therapists_aggregate.aggregate?.count || 0,
};
}

async function updateTherapistStatus(
client: ApolloClient<unknown>,
therapistId: string,
approvalStatus: Approval_Status_Enum,
) {
const { data } = await client.mutate({
mutation: UPDATE_THERAPIST_STATUS,
variables: {
therapist_id: therapistId,
approval_status: approvalStatus,
},
});

return data.update_therapist?.affected_rows || 0;
}

3) Approval Workflow Management

Approval Workflow Business Rules:

  • Document Review: Review uploaded professional documents
  • Approval Decision: Approve or reject therapist applications
  • Rejection Reasons: Provide specific reasons for rejection
  • Status Tracking: Track approval status and timeline
  • Notification System: Notify therapists of approval decisions

Approval Logic:

// Approval workflow validation
const validateApprovalDecision = (
therapistId: string,
decision: 'APPROVED' | 'REJECTED',
reason?: string,
) => {
const errors: string[] = [];

if (!therapistId) {
errors.push('Therapist ID is required');
}

if (decision === 'REJECTED' && !reason?.trim()) {
errors.push('Rejection reason is required');
}

// Check if therapist has required documents
// Check if therapist meets minimum requirements

return errors;
};

// Process approval decision
const processApprovalDecision = (
therapistId: string,
decision: 'APPROVED' | 'REJECTED',
reason?: string,
) => {
return updateTherapistStatus(therapistId, decision).then(() => {
if (decision === 'REJECTED' && reason) {
return addRejectionReason(therapistId, reason);
}
});
};

// Get pending therapists for review
const getPendingTherapists = () => {
return getTherapistList({
where: { approval_status: { _eq: 'PENDING' } },
order_by: [{ created_at: 'asc' }],
});
};

4) Child Assignment Management

Child Assignment Business Rules:

  • Specialization Matching: Match therapists with children based on specializations
  • Workload Management: Consider therapist current workload and capacity
  • Assignment History: Track assignment history and changes
  • Performance Monitoring: Monitor therapist-child relationship effectiveness
  • Bulk Assignment: Assign multiple children to therapists

Assignment Logic:

// Child assignment validation
const validateChildAssignment = (therapistId: string, childId: string) => {
const errors: string[] = [];

if (!therapistId) {
errors.push('Therapist ID is required');
}

if (!childId) {
errors.push('Child ID is required');
}

// Check if therapist is approved and active
// Check if therapist has appropriate specializations
// Check if assignment already exists
// Check therapist workload capacity

return errors;
};

// Get available therapists for child
const getAvailableTherapists = (childId: string) => {
return getTherapistList({
where: {
_and: [
{ approval_status: { _eq: 'APPROVED' } },
{ status: { _eq: 'ACTIVE' } },
// Add specialization matching logic
],
},
});
};

// Bulk child assignment
const assignMultipleChildren = (therapistId: string, childIds: string[]) => {
return Promise.all(
childIds.map((childId) => assignChildToTherapist(therapistId, childId)),
);
};

5) Therapist Performance & Analytics

Performance Tracking Business Rules:

  • Session Tracking: Track therapy sessions and attendance
  • Client Satisfaction: Monitor parent and child satisfaction ratings
  • Outcome Measurement: Measure therapy outcomes and progress
  • Performance Metrics: Calculate performance indicators and KPIs
  • Reporting: Generate performance reports and analytics

Performance Analytics Implementation:

// Therapist performance metrics
interface TherapistPerformance {
therapist_id: string;
total_sessions: number;
completed_sessions: number;
attendance_rate: number;
average_rating: number;
client_satisfaction: number;
outcome_scores: OutcomeScore[];
monthly_stats: MonthlyStats[];
}

// Calculate performance metrics
const calculatePerformanceMetrics = (
therapistId: string,
dateRange: DateRange,
) => {
return Promise.all([
getSessionStats(therapistId, dateRange),
getClientRatings(therapistId, dateRange),
getOutcomeScores(therapistId, dateRange),
]).then(([sessions, ratings, outcomes]) => {
return {
therapist_id: therapistId,
total_sessions: sessions.total,
completed_sessions: sessions.completed,
attendance_rate: (sessions.completed / sessions.total) * 100,
average_rating: ratings.average,
client_satisfaction: ratings.satisfaction,
outcome_scores: outcomes,
};
});
};

// Generate performance report
const generatePerformanceReport = (therapistId: string, period: string) => {
return getTherapistDetails(therapistId).then((therapist) => {
return calculatePerformanceMetrics(therapistId, getDateRange(period)).then(
(metrics) => {
return {
therapist: therapist,
metrics: metrics,
period: period,
generated_at: new Date().toISOString(),
};
},
);
});
};

Data Flow (Web ↔ Backend)

Critical Business Logic Flow:

  1. Therapist Listing: Load therapists → Apply status filtering → Search → Sort → Paginate
  2. Profile Management: Create/Edit therapist → Validate data → Upload documents → Assign specializations
  3. Approval Workflow: Review documents → Make approval decision → Update status → Notify therapist
  4. Child Assignment: Select therapist → Choose children → Validate compatibility → Create assignments

GraphQL Operations with Business Rules:

ActionOperationBusiness Rules
List TherapistsgetTherapistList(where, order_by)Status-based filtering, search capabilities
Create TherapistcreateTherapist(input)Document validation, specialization assignment
Update StatusupdateTherapistStatus(therapist_id, status)Approval workflow validation
Assign ChildassignChildToTherapist(therapist_id, child_id)Specialization matching, workload validation
Delete TherapistsdeleteTherapists(therapist_ids)Bulk deletion with confirmation

Error Handling & Validation:

  • Therapist Not Found: "Therapist not found or access denied"
  • Invalid Specialization: "Therapist specialization does not match requirements"
  • Document Missing: "Required documents not uploaded"
  • Assignment Conflict: "Therapist already assigned to this child"
  • Workload Exceeded: "Therapist workload capacity exceeded"

Security & Access Control

  • Admin-Only Access: Only admins can manage therapist profiles and assignments
  • Document Security: Professional documents protected by access controls
  • Approval Workflow: Multi-step approval process with audit trail
  • Data Privacy: Therapist data protected by role-based permissions
  • Assignment Controls: Child assignments require proper validation and authorization