-
Notifications
You must be signed in to change notification settings - Fork 430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ABDM Plug FE #9036
base: develop
Are you sure you want to change the base?
ABDM Plug FE #9036
Conversation
WalkthroughThis pull request introduces significant modifications to the component structure and routing within the application. A new Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
❌ Deploy Preview for care-ohc failed.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Outside diff range and nitpick comments (17)
src/App.tsx (2)
15-30
: Provider hierarchy looks good, but needs documentation.The new provider hierarchy with PubSubProvider as the outermost wrapper is well-structured and enables event-driven communication across the application. The placement of components within their respective providers is correct.
Consider adding a comment block above the return statement documenting the provider hierarchy and its purpose:
const App = () => { + /** + * Provider Hierarchy: + * 1. PubSubProvider - Enables event-driven communication across the app + * 2. PluginEngine - Manages plugin-based architecture + * 3. HistoryAPIProvider - Provides routing history context + * 4. AuthUserProvider - Manages authentication state + * 5. FeatureFlagsProvider - Controls feature toggles + */ return (
15-30
: Consider adding error boundaries.Since this is the main App component with multiple providers and integrations, it would be beneficial to add error boundaries to gracefully handle provider-level failures.
Consider wrapping key sections with error boundaries:
import { ErrorBoundary } from 'react-error-boundary'; // Example usage: <ErrorBoundary fallback={<ErrorFallback />}> <PubSubProvider> <PluginEngine> {/* ... */} </PluginEngine> </PubSubProvider> </ErrorBoundary>src/Utils/pubsubContext.tsx (3)
3-12
: Consider improving type safety with generic type parameters.The current implementation uses
unknown
for message types, which loses type safety. Consider parameterizing the types to maintain type safety throughout the pub/sub system.-export type Handler = (message: unknown) => Promise<void>; +export type Handler<T = unknown> = (message: T) => Promise<void>; + +export type Subscribers = Record<string, Set<Handler>>; + export type PubSubContext = { - subscribe: (topic: string, handler: Handler) => void; - unsubscribe: (topic: string, handler: Handler) => void; - publish: (topic: string, message: unknown) => void; - subscribers: Record<string, Set<Handler>>; - setSubscribers: React.Dispatch<React.SetStateAction<Record<string, Set<Handler>>>>; + subscribe: <T>(topic: string, handler: Handler<T>) => void; + unsubscribe: <T>(topic: string, handler: Handler<T>) => void; + publish: <T>(topic: string, message: T) => void; + // Consider making these private or removing from the public interface - subscribers: Subscribers; - setSubscribers: React.Dispatch<React.SetStateAction<Subscribers>>; };
16-61
: Implement cleanup mechanism to prevent memory leaks.Components might forget to unsubscribe, leading to memory leaks. Consider adding automatic cleanup using React's useEffect.
Consider implementing a higher-order component or custom hook for automatic cleanup:
export const useSubscription = <T>(topic: string, handler: Handler<T>) => { const { subscribe, unsubscribe } = usePubSub(); useEffect(() => { subscribe(topic, handler); return () => unsubscribe(topic, handler); }, [topic, handler]); };
63-71
: Enhance error message with debugging information.While the error check is good, the error message could be more helpful for debugging.
export const usePubSub = () => { const context = useContext(PubSubContext); if (!context) { - throw new Error("usePubSub must be used within PubSubProvider"); + throw new Error( + "usePubSub must be used within PubSubProvider. " + + "Please ensure the component is wrapped in a PubSubProvider component. " + + "Check the component hierarchy or refer to documentation for proper setup." + ); } return context; };src/pluginTypes.ts (3)
2-2
: Consider standardizing import paths.The file mixes relative and absolute import paths (e.g.,
"./components/..."
vs"@/components/..."
). Consider standardizing to absolute imports using the@
alias for better maintainability and consistency.Also applies to: 7-11
24-25
: Add JSDoc comments for the ExtendPatientInfoCardComponentType.Consider adding documentation to explain the purpose and usage of this extension point in the plugin system.
43-56
: Improve type safety in ExtendPatientRegisterFormComponentType.The form state uses
any
type which reduces type safety. Consider:
- Creating a specific type for the form state
- Using a generic type parameter for the form data
+interface PatientFormState { + form: Partial<PatientForm>; + errors: Record<keyof PatientForm, string>; +} export type ExtendPatientRegisterFormComponentType = React.FC<{ facilityId: string; patientId?: string; - state: { - form: { - [key: string]: any; - }; - errors: { - [key: string]: string; - }; - }; + state: PatientFormState; dispatch: React.Dispatch<any>; field: FormContextValue<PatientForm>; }>;src/components/Facility/FacilityConfigure.tsx (2)
Line range hint
14-42
: Enhance type safety and form validationConsider improving the component's type safety and form validation:
- Replace
any
type in the reducer with proper interfaces- Add zod/yup schema validation for the form
- Define proper error types
Example implementation:
interface FacilityForm { name: string; state: number; district: number; localbody: number; ward: number; middleware_address: string; } interface FormState { form: FacilityForm; errors: Partial<Record<keyof FacilityForm, string[]>>; } type FormAction = | { type: "set_form"; form: FacilityForm } | { type: "set_error"; errors: FormState["errors"] }; const FormReducer = (state: FormState, action: FormAction): FormState => { switch (action.type) { case "set_form": { return { ...state, form: action.form, }; } case "set_error": { return { ...state, errors: action.errors, }; } } };
Line range hint
71-91
: Refactor middleware address validationThe middleware address validation logic should be extracted and documented:
const MIDDLEWARE_ADDRESS_PATTERN = /^(?!https?:\/\/)[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*\.[a-zA-Z]{2,}$/; /** * Validates middleware address format * - Must not start with http:// or https:// * - Must be a valid domain name * - Allows alphanumeric characters, hyphens, and underscores */ const validateMiddlewareAddress = (address: string) => { if (!address) { return "Middleware Address is required"; } if (!MIDDLEWARE_ADDRESS_PATTERN.test(address)) { return "Invalid Middleware Address"; } return null; }; // Usage in handleSubmit const error = validateMiddlewareAddress(state.form.middleware_address); if (error) { dispatch({ type: "set_error", errors: { middleware_address: [error] }, }); setIsLoading(false); return; }src/components/Facility/ConsultationDetails/index.tsx (3)
209-285
: Consider extracting header components and utilitiesThe header section contains repeated patterns and complex conditional logic that could be simplified.
Suggestions:
- Extract button components:
interface ActionButtonProps { onClick?: () => void; href?: string; children: React.ReactNode; id?: string; } const ActionButton: React.FC<ActionButtonProps> = ({ onClick, href, children, id }) => { const className = "btn btn-primary m-1 w-full hover:text-white"; return href ? ( <Link href={href} className={className} id={id}> {children} </Link> ) : ( <button onClick={onClick} className={className} id={id}> {children} </button> ); };
- Extract header actions into a separate component:
const ConsultationActions: React.FC<{ consultationData: ConsultationModel; patientData: PatientModel; showDoctors: boolean; setShowDoctors: (show: boolean) => void; }> = ({ consultationData, patientData, showDoctors, setShowDoctors }) => { // ... action buttons logic };
286-365
: Enhance accessibility and error handlingThe patient info section could benefit from improved accessibility and error handling.
Suggestions:
- Add ARIA labels for better screen reader support:
- <div className="mt-2 rounded-lg border bg-secondary-100 p-2 md:mt-0"> + <div + className="mt-2 rounded-lg border bg-secondary-100 p-2 md:mt-0" + role="region" + aria-label="Patient admission status" + >
- Add error boundaries for date formatting:
const formatDateSafely = (date: string | null | undefined): string => { try { return date ? formatDateTime(date) : ''; } catch (error) { console.error('Date formatting error:', error); return 'Invalid date'; } };
366-397
: Simplify tab visibility logicThe tab visibility logic, especially for the feed tab, is complex and could be simplified.
Suggested implementation:
const isTabVisible = (tabKey: string) => { if (tabKey !== 'FEED') return true; return !!( isCameraAttached && !consultationData?.discharge_date && consultationData?.current_bed?.bed_object?.id && CameraFeedPermittedUserTypes.includes(authUser.user_type) ); }; // In JSX: {keysOf(TABS).map((p) => isTabVisible(p) && ( <Link key={p} className={tabButtonClasses(tab === p)} href={`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/${p.toLocaleLowerCase()}`} > {t(`CONSULTATION_TAB__${p}`)} </Link> ) )}src/components/Facility/FacilityHome.tsx (1)
428-431
: Consider adding error boundariesWhile the integration of
PLUGIN_Component
is good, consider wrapping it with an error boundary to prevent plugin failures from affecting the entire facility management interface.+import { ErrorBoundary } from 'react-error-boundary'; +const PluginErrorFallback = () => ( + <div className="text-sm text-error-600"> + Failed to load plugin options + </div> +); <DropdownMenu> {/* ... other items ... */} + <ErrorBoundary FallbackComponent={PluginErrorFallback}> <PLUGIN_Component __name="ManageFacilityOptions" facility={facilityData} /> + </ErrorBoundary> </DropdownMenu>src/components/Facility/ConsultationDetails/ConsultationContext.tsx (1)
62-64
: Eliminate redundant type assertion when providing context valueThe explicit type casting to
ConsultationContextType<T>
may be unnecessary if the object already conforms to the type. Allowing TypeScript to infer the type can improve type safety and clarity.Consider updating the context provider value like this:
- value={ - { - ...state, - setValue, - } as ConsultationContextType<T> - } + value={{ + ...state, + setValue, + }}src/components/Patient/PatientInfoCard.tsx (1)
856-856
: Limit props passed toExtendPatientInfoCard
pluginConsider passing only the necessary props to
ExtendPatientInfoCard
to prevent unintentional exposure of sensitive data.Apply this diff to pass only required props:
- <PLUGIN_Component __name="ExtendPatientInfoCard" {...props} /> + <PLUGIN_Component __name="ExtendPatientInfoCard" patient={patient} consultation={consultation} />Replace
patient
andconsultation
with the specific props needed by the plugin component.src/components/Patient/PatientRegister.tsx (1)
934-934
: Consider renaming__name
prop to adhere to naming conventionsThe prop
__name
with double underscores is unconventional in React components. Renaming it to a standard prop name likecomponentName
orname
would improve readability and align with common naming practices.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (28)
src/App.tsx
(1 hunks)src/Redux/api.tsx
(0 hunks)src/Routers/AppRouter.tsx
(0 hunks)src/Utils/pubsubContext.tsx
(1 hunks)src/common/constants.tsx
(0 hunks)src/common/hooks/useCareApps.ts
(1 hunks)src/components/ABDM/ABDMFacilityRecords.tsx
(0 hunks)src/components/ABDM/ABDMRecordsTab.tsx
(0 hunks)src/components/ABDM/ABHAProfileModal.tsx
(0 hunks)src/components/ABDM/ConfigureHealthFacility.tsx
(0 hunks)src/components/ABDM/FetchRecordsModal.tsx
(0 hunks)src/components/ABDM/HealthInformation.tsx
(0 hunks)src/components/ABDM/LinkAbhaNumber/CreateWithAadhaar.tsx
(0 hunks)src/components/ABDM/LinkAbhaNumber/LinkWithOtp.tsx
(0 hunks)src/components/ABDM/LinkAbhaNumber/LinkWithQr.tsx
(0 hunks)src/components/ABDM/LinkAbhaNumber/index.tsx
(0 hunks)src/components/ABDM/LinkAbhaNumber/useMultiStepForm.ts
(0 hunks)src/components/ABDM/types/abha.ts
(0 hunks)src/components/ABDM/types/consent.ts
(0 hunks)src/components/ABDM/types/health-facility.ts
(0 hunks)src/components/ABDM/types/health-information.ts
(0 hunks)src/components/Facility/ConsultationDetails/ConsultationContext.tsx
(1 hunks)src/components/Facility/ConsultationDetails/index.tsx
(4 hunks)src/components/Facility/FacilityConfigure.tsx
(2 hunks)src/components/Facility/FacilityHome.tsx
(2 hunks)src/components/Patient/PatientInfoCard.tsx
(2 hunks)src/components/Patient/PatientRegister.tsx
(4 hunks)src/pluginTypes.ts
(4 hunks)
💤 Files with no reviewable changes (18)
- src/Redux/api.tsx
- src/Routers/AppRouter.tsx
- src/common/constants.tsx
- src/components/ABDM/ABDMFacilityRecords.tsx
- src/components/ABDM/ABDMRecordsTab.tsx
- src/components/ABDM/ABHAProfileModal.tsx
- src/components/ABDM/ConfigureHealthFacility.tsx
- src/components/ABDM/FetchRecordsModal.tsx
- src/components/ABDM/HealthInformation.tsx
- src/components/ABDM/LinkAbhaNumber/CreateWithAadhaar.tsx
- src/components/ABDM/LinkAbhaNumber/LinkWithOtp.tsx
- src/components/ABDM/LinkAbhaNumber/LinkWithQr.tsx
- src/components/ABDM/LinkAbhaNumber/index.tsx
- src/components/ABDM/LinkAbhaNumber/useMultiStepForm.ts
- src/components/ABDM/types/abha.ts
- src/components/ABDM/types/consent.ts
- src/components/ABDM/types/health-facility.ts
- src/components/ABDM/types/health-information.ts
🧰 Additional context used
🪛 Biome
src/common/hooks/useCareApps.ts
[error] 29-29: Avoid the use of spread (...
) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce
) because it causes a time complexity of O(n^2)
.
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
🔇 Additional comments (14)
src/App.tsx (2)
10-10
: LGTM!
The import statement is correctly structured and follows React conventions.
15-30
: Verify PubSub usage across the application.
Let's ensure that all components requiring pub/sub functionality are properly wrapped within the PubSubProvider.
✅ Verification successful
PubSubProvider is correctly positioned and all usages are properly wrapped
The verification shows that:
- The
PubSubProvider
is placed at the root level inApp.tsx
, wrapping all other components - Only two components use the pub/sub functionality:
PatientRegister.tsx
usesusePubSub
hook for publishing eventsNotificationsList.tsx
uses subscribe/unsubscribe (but for push notifications, not related to PubSubContext)
- The context implementation in
pubsubContext.tsx
includes proper error handling for usage outside the provider
All components using pub/sub functionality are properly wrapped within the PubSubProvider's scope.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Find all usages of usePubSub hook to verify they're within PubSubProvider
echo "Searching for usePubSub hook usage..."
rg "usePubSub" --type ts --type tsx
echo -e "\nSearching for direct PubSubContext usage..."
rg "PubSubContext" --type ts --type tsx
echo -e "\nSearching for publish/subscribe method calls..."
rg -e "publish\(" -e "subscribe\(" --type ts --type tsx
Length of output: 516
Script:
#!/bin/bash
# Let's try without specifying file types since tsx is not recognized
echo "Searching for usePubSub hook usage..."
rg "usePubSub"
echo -e "\nSearching for direct PubSubContext usage..."
rg "PubSubContext"
echo -e "\nSearching for publish/subscribe method calls..."
rg -e "publish\(" -e "subscribe\("
# Also search for the PubSubProvider definition to understand its scope
echo -e "\nSearching for PubSubProvider definition..."
rg "PubSubProvider"
Length of output: 1998
src/common/hooks/useCareApps.ts (1)
25-31
: Verify plugin integration for consultation tabs.
Since this hook is part of the ABDM patient management migration to plugins, we should verify that the consultation tabs are correctly loaded from plugins.
✅ Verification successful
Let me gather more information about the plugin integration by examining the plugin types and related implementations.
Let me check one more thing to verify the plugin loading mechanism and how consultation tabs are registered.
Based on the gathered information, I can now provide the final response:
Plugin integration for consultation tabs is correctly implemented.
The implementation follows the plugin architecture:
- Plugin manifest type correctly defines
consultationTabs
as an optional field that accepts lazy-loaded React components - The
useCareAppConsultationTabs
hook properly aggregates consultation tabs from all registered plugins - The consultation tabs are correctly integrated into the main ConsultationDetails component with proper type safety and props passing
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consultation tabs implementation in plugins
# Expected: Find plugin manifest definitions that include consultationTabs
# Search for plugin manifest files
echo "Searching for plugin manifest definitions with consultationTabs..."
rg -l "consultationTabs.*=|consultationTabs.*:"
# Search for consultation tab implementations
echo "Searching for consultation tab component implementations..."
ast-grep --pattern 'export const $_ = () => {
$$$
consultationTabs
$$$
}'
Length of output: 422
Script:
#!/bin/bash
# Check plugin type definitions and implementations
echo "Checking plugin type definitions..."
cat src/pluginTypes.ts
echo -e "\nSearching for care app plugin implementations..."
rg -A 10 "implements.*CareApp"
echo -e "\nSearching for consultation tab usages..."
rg -A 5 "consultationTabs"
Length of output: 4513
Script:
#!/bin/bash
# Check plugin loading and registration
echo "Checking plugin loading mechanism..."
rg -A 10 "useCareApps.*=.*{"
echo -e "\nChecking plugin manifest loading..."
rg -A 10 "loadPluginManifest|registerPlugin"
echo -e "\nChecking consultation tab component usage..."
rg -A 5 "ConsultationTabProps"
Length of output: 20693
🧰 Tools
🪛 Biome
[error] 29-29: Avoid the use of spread (...
) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce
) because it causes a time complexity of O(n^2)
.
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
src/Utils/pubsubContext.tsx (1)
1-71
: Verify proper usage of PubSubProvider in the codebase.
Let's ensure the provider is properly placed in the component hierarchy and that there are no direct context usage bypassing the hook.
✅ Verification successful
Based on the gathered information, I can now provide a final response:
PubSub implementation appears sound with proper provider placement and usage patterns
- PubSubProvider is correctly placed high in the component tree in App.tsx
- No direct context usage found outside the provided hook
- Current usage in PatientRegister.tsx follows proper patterns with publish
- No evidence of subscribe without cleanup was found in the codebase
- The implementation provides proper type safety and error boundaries
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify PubSubProvider usage and potential issues
# Test 1: Check if PubSubProvider is used at the root level
echo "Checking PubSubProvider placement..."
ast-grep --pattern 'function App() {
return (
$$$
<PubSubProvider>
$$$
</PubSubProvider>
$$$
)
}'
# Test 2: Check for direct context usage which might bypass the hook
echo "Checking for direct context usage..."
rg "useContext\(PubSubContext\)" --type ts --type tsx
# Test 3: Look for potential memory leaks (subscribe without unsubscribe)
echo "Checking for potential memory leaks..."
rg "subscribe\(" -A 10 --type ts --type tsx
Length of output: 536
Script:
#!/bin/bash
# Let's try a different approach with more generic searches
# Check PubSubProvider usage
echo "Checking PubSubProvider usage..."
rg "<PubSubProvider" -A 3
# Check direct context usage
echo "Checking direct context usage..."
rg "PubSubContext" -A 2
# Check subscribe/unsubscribe patterns
echo "Checking subscribe/unsubscribe patterns..."
rg "usePubSub" -A 5
Length of output: 2861
Script:
#!/bin/bash
# Let's check for proper cleanup in components using subscribe
# Look for useEffect with subscribe
echo "Checking subscribe cleanup patterns..."
rg -B 2 -A 10 "useEffect.*subscribe"
# Look for all publish usages to understand the communication patterns
echo "Checking publish usages..."
rg "publish\(" -A 2
# Check if PubSubProvider is the root provider
echo "Checking provider hierarchy..."
rg -A 10 "function App"
Length of output: 1011
src/pluginTypes.ts (2)
61-67
: LGTM! Well-structured component type additions.
The new component types follow consistent naming patterns and align well with the plugin architecture.
91-94
: Document the consultationTabs property and verify lazy loading.
Please add JSDoc comments explaining the purpose and structure of consultationTabs. Also, ensure that all consultation tab components are properly registered and loaded.
✅ Verification successful
Based on the gathered information, I can now generate the final response:
Lazy loading implementation is properly structured and consultation tabs are correctly registered
The codebase shows a well-implemented system for consultation tabs:
- ConsultationTabProps interface is properly defined with all required properties
- Existing tabs are correctly implemented using the ConsultationTabProps interface
- Dynamic tab registration is handled through useCareAppConsultationTabs hook
- Lazy loading is properly implemented through the plugin system
The review comment's concern about verification has been addressed, as the implementation shows proper type safety and component registration. Adding JSDoc comments would still be beneficial for documentation purposes.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consultation tab component implementations
# Expected: Find all consultation tab components to ensure they match the manifest type
# Search for consultation tab component implementations
rg -t typescript -t javascript "React\.FC<ConsultationTabProps>" -A 5
# Search for consultation tab registrations in plugin manifests
rg -t typescript -t javascript "consultationTabs.*=.*{" -A 5
Length of output: 277
Script:
#!/bin/bash
# Search for consultation tab component implementations with fixed regex
rg "React\.FC.*ConsultationTabProps"
# Search for consultation tab registrations with fixed regex
rg "consultationTabs.*="
# Search for files containing ConsultationTabProps to understand usage
rg "ConsultationTabProps"
# Find all typescript/javascript files that might contain tab implementations
fd "\.(ts|tsx|js|jsx)$" | grep -i "tab"
Length of output: 6306
Script:
#!/bin/bash
# Let's check the ConsultationTabProps interface definition
cat src/components/Facility/ConsultationDetails/index.tsx
# Check if there are any existing plugin manifests using consultationTabs
fd "manifest" | grep -i "plugin" | xargs cat
Length of output: 16321
src/components/Facility/FacilityConfigure.tsx (2)
163-166
: Verify the ExtendFacilityConfigure plugin implementation
The integration looks clean, but we should verify the existence and implementation of the "ExtendFacilityConfigure" plugin.
#!/bin/bash
# Description: Verify plugin implementation and usage
# Test 1: Look for the plugin implementation
rg -A 5 "ExtendFacilityConfigure.*export"
# Test 2: Check for any existing usages or references
rg "ExtendFacilityConfigure" -g "!{FacilityConfigure.tsx}"
13-13
: Verify plugin engine setup and configuration
The introduction of PLUGIN_Component
suggests a shift to a plugin-based architecture. Let's verify the plugin system setup.
✅ Verification successful
Plugin system is properly configured and in active use
The plugin system is well-established in the codebase:
PLUGIN_Component
is properly exported fromsrc/PluginEngine.tsx
- The component is used consistently across multiple files with proper typing
ExtendFacilityConfigure
is correctly typed inpluginTypes.ts
with expected props- The plugin architecture is actively used in various components including patient, facility, and consultation features
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify plugin engine setup and configuration
# Test 1: Check if plugin engine exists and is properly exported
rg -l "export.*PLUGIN_Component" "src/PluginEngine"
# Test 2: Check for other components using the plugin system
rg "PLUGIN_Component.*ExtendFacility" -g "!{FacilityConfigure.tsx}"
Length of output: 361
Script:
#!/bin/bash
# Let's verify the plugin system setup more thoroughly
# Check for PLUGIN_Component definition and exports
rg -l "PLUGIN_Component" --type ts --type tsx
# Check the actual implementation/definition
rg -A 5 "PLUGIN_Component" --type ts --type tsx
# Look for plugin types and interfaces
rg -A 5 "ExtendFacilityConfigureComponentType" --type ts --type tsx
# Check for plugin registration or initialization
rg -A 5 "registerPlugin|initializePlugin" --type ts --type tsx
Length of output: 338
Script:
#!/bin/bash
# Let's try without explicit file type flags since tsx isn't recognized
# Check for PLUGIN_Component definition and exports
rg -l "PLUGIN_Component"
# Check the actual implementation/definition
rg -A 5 "PLUGIN_Component"
# Look for plugin types and interfaces
rg -A 5 "ExtendFacilityConfigureComponentType"
# Check for plugin system files
fd "PluginEngine|pluginTypes"
Length of output: 8412
src/components/Facility/ConsultationDetails/index.tsx (3)
42-43
: LGTM: Type safety improvements
Good addition of explicit typing for the TABS object and clean introduction of new imports for consultation context management.
Also applies to: 67-67
202-207
: LGTM: Clean context implementation
Good use of React Context to share consultation and patient data with child components.
403-418
: LGTM: Clean modal implementation
Good implementation of modal/slideover components with proper state management.
src/components/Facility/FacilityHome.tsx (2)
50-50
: LGTM: Plugin architecture integration
The import of PLUGIN_Component
aligns with the PR objective of moving ABDM functionality into a plugin-based architecture.
428-431
: Verify plugin component integration
Let's verify that the plugin component is properly registered and handles all ABDM-related functionality that was previously available in the dropdown menu.
✅ Verification successful
Plugin component integration is properly configured
The verification shows that:
ManageFacilityOptions
is properly registered as a plugin component type inpluginTypes.ts
- ABDM functionality is configured in
care.config.ts
with a feature flag - The
PLUGIN_Component
usage inFacilityHome.tsx
follows the correct pattern seen across other plugin integrations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the plugin component registration and ABDM functionality migration
# Test 1: Check if the plugin component is properly registered
echo "Checking plugin component registration..."
rg -l "ManageFacilityOptions.*=.*{" --type ts
# Test 2: Verify that ABDM-related code has been moved to the plugin
echo "Verifying ABDM code migration..."
rg -l "abdm" --type ts
# Test 3: Check for any remaining ABDM-related components in the facility management
echo "Checking for remaining ABDM components..."
rg -l "ABDM.*Record|Record.*ABDM" --type ts
Length of output: 510
Script:
#!/bin/bash
# Let's try a different approach to verify the plugin component
# Check for ManageFacilityOptions plugin registration
echo "Checking for ManageFacilityOptions plugin..."
rg -A 5 "ManageFacilityOptions" --type ts
# Check ABDM related functionality in care.config.ts
echo "Checking ABDM configuration..."
cat care.config.ts
# Look for any PLUGIN_Component usage
echo "Checking PLUGIN_Component usage..."
rg -A 3 "PLUGIN_Component" --type ts
Length of output: 9806
src/components/Patient/PatientInfoCard.tsx (1)
61-61
: Component props interface defined appropriately
The explicit definition of PatientInfoCardProps
enhances type safety and clarity.
Deploying care-fe with Cloudflare Pages
|
CARE Run #3839
Run Properties:
|
Project |
CARE
|
Branch Review |
abdm-plug-fe
|
Run status |
Passed #3839
|
Run duration | 04m 39s |
Commit |
6544233443: ABDM Plug FE
|
Committer | Khavin Shankar |
View all properties for this run ↗︎ |
Test results | |
---|---|
Failures |
0
|
Flaky |
0
|
Pending |
0
|
Skipped |
0
|
Passing |
124
|
View all changes introduced in this branch ↗︎ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (33)
cypress/e2e/patient_spec/PatientBedManagement.cy.ts (3)
Line range hint
6-17
: Consider extracting test data to fixtures.The test constants (bed and patient names) would be better maintained in a separate fixture file. This would:
- Make the test data more maintainable
- Allow reuse across different test files
- Make it easier to update test data in bulk
Consider creating a fixture file like this:
// cypress/fixtures/bed-management.json { "beds": { "bedOne": "Dummy Bed 4", "bedTwo": "Dummy Bed 1", "bedThree": "Dummy Bed 7" }, "patients": { "patientOne": "Dummy Patient 6", "patientTwo": "Dummy Patient 7" } }
Line range hint
31-54
: Enhance test coverage with error scenarios and additional assertions.While the happy path is well tested, consider adding:
- Error scenarios:
- Attempting to assign an already occupied bed
- Network failure during bed assignment
- Additional verifications:
- Bed status in the system after assignment
- Patient's location update in the system
Example test case to add:
it("Should handle bed assignment errors appropriately", () => { // First patient takes the bed patientPage.visitPatient(switchPatientOne); patientLogupdate.clickSwitchBed(); patientLogupdate.selectBed(switchBedOne); cy.verifyNotification("Bed allocated successfully"); // Second patient attempts to take the same bed patientPage.visitPatient(switchPatientTwo); patientLogupdate.clickSwitchBed(); patientLogupdate.selectBed(switchBedOne); cy.verifyNotification("Bed already occupied"); });
Line range hint
19-30
: Add documentation for test prerequisites and setup.Consider adding JSDoc comments to explain:
- Required test data setup
- Purpose of local storage management
- Required user permissions
Example documentation:
/** * Test suite for patient bed management functionality. * Prerequisites: * - District admin user with bed management permissions * - Available test beds: Dummy Bed 1, 4, 7 * - Test patients: Dummy Patient 6, 7 (should be admitted) * * Note: Local storage is preserved between tests to maintain user session * and cleared for filters to ensure consistent test state. */ describe("Patient switch bed functionality", () => {cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts (5)
1-4
: Consider standardizing import stylesThe imports use a mix of default and named import styles. Consider standardizing to named imports for consistency:
-import LoginPage from "../../pageobject/Login/LoginPage"; +import { LoginPage } from "../../pageobject/Login/LoginPage";
Line range hint
6-13
: Consider moving test data to fixturesThe test data (patient name, user roles) is currently hardcoded. Consider moving this to a fixture file for better maintainability and reusability:
// cypress/fixtures/doctorConnect.json { "patientName": "Dummy Patient 11", "users": { "doctor": "Dev Doctor", "nurse": "Dev Staff", "teleIcu": "Dev Doctor Two" } }Then in the test:
before(() => { cy.fixture('doctorConnect').then((data) => { this.testData = data; }); });
Line range hint
15-23
: Enhance URL assertion reliabilityInstead of using
cy.awaitUrl("/patients")
, consider using a more specific assertion:-cy.awaitUrl("/patients"); +cy.url().should('include', '/patients'); +cy.location('pathname').should('eq', '/patients');This provides better clarity on what exactly is being verified.
Line range hint
25-52
: Split test into smaller, focused test casesThe current test case covers multiple scenarios (icon visibility, phone copying, sorting). Consider splitting it into separate test cases for better maintainability and easier debugging:
it("should display correct user roles in their respective sections", () => { patientPage.visitPatient(patientName); doctorconnect.clickDoctorConnectButton(); cy.verifyContentPresence("#doctor-connect-home-doctor", [doctorUser]); cy.verifyContentPresence("#doctor-connect-home-nurse", [nurseUser]); cy.verifyContentPresence("#doctor-connect-remote-doctor", [teleIcuUser]); }); it("should copy phone number correctly", () => { doctorconnect.CopyFunctionTrigger(); doctorconnect.clickCopyPhoneNumber("#doctor-connect-home-doctor", doctorUser); doctorconnect.verifyCopiedContent(); }); it("should display communication icons", () => { doctorconnect.verifyIconVisible("#whatsapp-icon"); doctorconnect.verifyIconVisible("#phone-icon"); }); it("should sort users correctly by type", () => { // ... sorting tests });
Line range hint
54-56
: Consider adding more comprehensive cleanupWhile saving localStorage is good, consider adding more cleanup steps to ensure a clean state for subsequent test runs:
afterEach(() => { cy.saveLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.get('@cookies').then(cookies => { + cookies.forEach(cookie => cy.clearCookie(cookie.name)); + }); });src/components/Facility/ConsultationDetails/ConsultationContext.tsx (1)
13-19
: Consider improving type definition readability.While the type definition is technically correct, it could be more readable by breaking down the complex generic type into smaller, more focused types.
Consider this refactoring:
-type ConsultationContextType<T> = ConsultationContextBase & - T & { - setValue: <K extends keyof (ConsultationContextBase & T)>( - key: K, - value: (ConsultationContextBase & T)[K], - ) => void; - }; +type CombinedState<T> = ConsultationContextBase & T; +type SetValueFn<T> = <K extends keyof T>(key: K, value: T[K]) => void; + +type ConsultationContextType<T> = CombinedState<T> & { + setValue: SetValueFn<CombinedState<T>>; +};cypress/e2e/patient_spec/PatientFileUpload.ts (4)
Line range hint
10-13
: Consider extracting test data and improving hook specificity.The test structure is well-organized, but could be improved by:
- Moving test data (patient names, file names) to test fixtures
- Making before/beforeEach hooks more specific to their test cases
Example fixture structure:
// cypress/fixtures/patient-file-upload.json { "patients": { "audioTest": "Dummy Patient 3", "fileTest": "Dummy Patient 4", "permissionTest": "Dummy Patient 5" }, "files": { "audio": "cypress audio", "document": "cypress name", "modified": "cypress modified name" } }
Line range hint
33-57
: Enhance test coverage with error scenarios and validations.The current tests verify happy paths but should also cover:
- File size restrictions
- Supported file type validations
- Upload/download failure scenarios
- Content verification after download
Example additional test:
it("should handle file size restrictions", () => { const largeFile = 'sample-large-file.pdf'; // > allowed size patientPage.visitPatient(patientNameTwo); visitPatientFileUploadSection.call(patientFileUpload); patientFileUpload.uploadFile(largeFile); cy.verifyNotification("File size exceeds maximum limit"); });
Line range hint
108-116
: Enhance test customization and reduce duplication.The current reuse strategy is good but could be improved by:
- Allowing context-specific test customization
- Extracting common verification logic
- Parameterizing test behavior
Consider this enhanced approach:
interface TestConfig { context: 'details' | 'consultation'; skipTests?: string[]; customAssertions?: Record<string, () => void>; } function runTests( testDescription: string, visitPatientFileUploadSection: () => void, config: TestConfig ) { // Allow skipping specific tests based on context // Add custom assertions for different contexts }
Based on the gathered information from all the shell script executions, I can now provide the final response:
Test coverage for file permissions is incomplete
The current test only verifies rename permissions, but the PatientFileUpload component shows additional file operations that should be tested for permissions:
- File upload
- Audio recording
- File archiving
- File download
The review comment's concerns about hardcoded credentials and login state are valid, but the primary issue is incomplete permission testing coverage.
Suggested improvements:
- Test file upload permissions for different user roles
- Verify archive permissions across user roles
- Test audio recording permissions
- Verify download permissions for different users
- Move credentials to Cypress environment variables
Example:
it("verifies all file operation permissions", () => { const operations = ['upload', 'archive', 'rename', 'record', 'download']; const roles = ['nurse', 'doctor', 'district_admin']; roles.forEach(role => { cy.login(Cypress.env(`${role}_username`), Cypress.env(`${role}_password`)); operations.forEach(operation => { patientFileUpload.verifyOperationPermission(operation); }); }); });🔗 Analysis chain
Line range hint
59-106
: Improve security and completeness of permission testing.Current implementation has several areas for improvement:
- Hardcoded credentials should be moved to environment variables or secure fixtures
- Additional permission-based actions should be verified (delete, archive, etc.)
- Login state should be properly cleaned between tests
Let's verify if there are other permission-based actions that should be tested:
Consider this improved approach:
// Use env variables for credentials Cypress.env('NURSE_1_USERNAME') Cypress.env('NURSE_1_PASSWORD') // Verify all permission-based actions it("should verify all permission-based actions", () => { const actions = ['rename', 'delete', 'archive', 'download']; actions.forEach(action => { patientFileUpload.verifyActionPermission(action, userRole); }); });
Let me search for these patterns to understand the permission system and available file actions in the codebase. This will help verify if there are other permission-based actions that should be tested in the cypress spec.
I want to verify the available file actions and permission checks to ensure we're testing all relevant permissions in the test case.
I want to verify all available file actions in the component to ensure we're testing all permission-based operations comprehensively.
I want to check the page object implementation and all file permission-related tests to understand the complete scope of file operations and permissions being tested.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for permission checks in related components rg -t tsx -t ts "can|hasPermission|isAllowed" --glob "!cypress/**"Length of output: 96
Script:
#!/bin/bash # Search for permission checks in related components with correct file extensions rg -t ts -t js "can|hasPermission|isAllowed" --glob "!cypress/**" -A 2 # Also search for file-related actions in the codebase rg -t ts -t js "file\.(delete|archive|download|rename)" --glob "!cypress/**" -A 2 # Look for permission-related components or utilities fd -e ts -e js "permission|auth" --exclude "cypress"Length of output: 45039
Script:
#!/bin/bash # Let's check the file upload component and related files for permission checks ast-grep --pattern 'verifyFileRenameOption|verifyUploadFilePresence|verifyArchiveFile' # Search for file-related actions in the patient file upload component rg -t ts "clickSaveArchiveFile|clickSaveFileName|uploadFile|renameFile" cypress/e2e/patient_spec/PatientFileUpload.ts -A 2 # Look for file permission checks in the codebase rg -t ts -t js "hasPermission.*file|canEdit.*file|canArchive.*file" --glob "!cypress/**"Length of output: 1155
Script:
#!/bin/bash # Let's check the patient file upload component for all available actions rg -t ts "^[^/].*\{" cypress/e2e/patient_spec/PatientFileUpload.ts -A 5 # Search for file-related actions in the component class rg -t ts "class PatientFileUpload" cypress/e2e/patient_spec/PatientFileUpload.ts -A 50 # Look for file-related permission tests in other spec files rg -t ts "file.*permission|permission.*file" cypress/e2e/patient_spec/Length of output: 1923
Script:
#!/bin/bash # Check the page object file for available file operations rg -t ts "class PatientFileUpload" cypress/pageobject/Patient/PatientFileupload.ts -A 50 # Look for file permission tests in the entire cypress directory rg -t ts "it\(.*file.*permission" cypress/ -B 2 -A 10Length of output: 1571
cypress/e2e/assets_spec/AssetsCreation.cy.ts (5)
Line range hint
16-25
: Consider adding error handling for login failures.While the setup is well-structured, consider adding error handling for the login process to make tests more robust.
before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginAsDistrictAdmin().then(() => { + // Verify successful login + cy.url().should('not.include', '/login'); + cy.get('[data-testid="user-menu"]').should('exist'); + }); cy.saveLocalStorage(); });
Line range hint
27-37
: Consider using data-driven testing for validation.The empty field validation test could be more maintainable using a data-driven approach.
+const validationCases = [ + { field: 'asset-name', error: 'Asset Name cannot be empty' }, + { field: 'location', error: 'Location cannot be empty' }, + { field: 'status', error: 'Status cannot be empty' }, + { field: 'phone', error: 'Phone number cannot be empty' } +]; + it("Verify asset creation fields throws error if empty", () => { assetPage.createAsset(); assetPage.selectFacility("Dummy Facility 40"); assetPage.clickCreateAsset(); - assetPage.verifyEmptyAssetNameError(); - assetPage.verifyEmptyLocationError(); - assetPage.verifyEmptyStatusError(); - assetPage.verifyEmptyPhoneError(); + validationCases.forEach(({ field, error }) => { + cy.get(`[data-testid="${field}-error"]`).should('contain', error); + }); });
Line range hint
41-93
: Improve test isolation and constants management.The asset creation test creates multiple assets in a single test case. Consider:
- Splitting into separate test cases for better isolation
- Moving constants to a separate configuration file
+// constants.ts +export const TEST_DATA = { + facility: "Dummy Facility 40", + location: "Camera Loc", + assetClass: "ONVIF Camera", + defaultPhone: "9999999999", + defaultEmail: "[email protected]", + defaultWarranty: "2025-12-25" +}; -it("Create an Asset", () => { +it("should create first asset successfully", () => { assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 40"); + assetPage.selectFacility(TEST_DATA.facility); // ... rest of the first asset creation assetPage.verifySuccessNotification("Asset created successfully"); }); +it("should create second asset successfully", () => { + assetPage.createAsset(); // ... second asset creation logic });
Line range hint
147-170
: Split vital monitor test into separate creation and configuration tests.The vital monitor test combines multiple concerns. Consider splitting it for better maintainability and clearer failure isolation.
-it("Add an vital monitor asset and configure it", () => { +it("should create vital monitor asset successfully", () => { // ... asset creation logic assetPage.verifyAssetCreation(); +}); + +it("should configure vital monitor asset successfully", () => { assetSearchPage.typeSearchKeyword("New Test Asset Vital"); assetSearchPage.pressEnter(); assetPage.openCreatedAsset(); assetPage.configureVitalAsset("Host name", "192.168.1.20"); assetPage.clickConfigureVital(); });
Line range hint
1-179
: Consider implementing custom commands for common operations.To improve maintainability and reduce code duplication, consider:
- Creating custom Cypress commands for common operations like asset creation and configuration
- Implementing a proper test data management strategy
- Adding retry strategies for potentially flaky operations
Example custom command:
// commands.ts Cypress.Commands.add('createBasicAsset', (assetData) => { const assetPage = new AssetPage(); assetPage.createAsset(); assetPage.selectFacility(assetData.facility); // ... common asset creation steps return cy.wrap(assetPage); });cypress/e2e/assets_spec/AssetsManage.cy.ts (1)
Line range hint
1-116
: Well-structured test suite with comprehensive coverage.The test suite demonstrates several strengths:
- Proper use of page object pattern for maintainability
- Comprehensive test coverage for asset management features
- Good test isolation with proper hooks and local storage handling
- Clear test descriptions and logical flow
However, there are a few suggestions to enhance the test suite further:
- Consider extracting test data to fixtures:
+ // Move to cypress/fixtures/assets.json + { + "facilityName": "Dummy Facility 40", + "assetName": "Dummy Camera", + "locationName": "Dummy Location 1", + "initialLocationName": "Camera Location" + } - const fillFacilityName = "Dummy Facility 40"; - const assetname = "Dummy Camera"; - const locationName = "Dummy Location 1"; - const initiallocationName = "Camera Location"; + const testData = require('../../fixtures/assets.json');
- Consider adding custom commands for common operations:
// In commands.ts Cypress.Commands.add('setupAssetTest', (assetName: string) => { cy.get('@assetSearchPage').typeSearchKeyword(assetName); cy.get('@assetSearchPage').pressEnter(); cy.get('@assetSearchPage').verifyBadgeContent(assetName); cy.get('@assetSearchPage').clickAssetByName(assetName); });This would reduce repetition in multiple test cases where you search and select an asset.
cypress/e2e/users_spec/UsersManage.cy.ts (1)
Line range hint
7-171
: Consider adding test cases for error scenarios.While the happy path scenarios are well covered, consider adding test cases for:
- Invalid user searches
- Network failures during facility linking
- Edge cases in working hours validation
cypress/e2e/patient_spec/PatientPrescription.cy.ts (1)
Line range hint
16-168
: Consider adding tests for event-driven scenarios.With the introduction of PubSubProvider for event-driven communication, consider adding test cases that specifically verify:
- Event propagation for medicine administration updates
- Real-time updates in the UI when prescriptions change
- Proper cleanup of event subscriptions
Example test structure:
it("should update UI in real-time when prescription changes", () => { // Setup multiple browser tabs/windows // Make changes in one tab // Verify updates are reflected in other tabs // Verify proper cleanup of subscriptions });cypress/e2e/users_spec/UsersCreation.cy.ts (1)
Line range hint
11-246
: Consider these improvements for better test maintainability.While the test implementation is functional, here are some suggestions to enhance maintainability:
- Move test data to fixtures:
// cypress/fixtures/userData.json { "fillFacilityName": "Dummy Facility 40", "alreadylinkedusersviews": ["devdoctor", "devstaff2", "devdistrictadmin"], "EXPECTED_ERROR_MESSAGES": [...], "EXPECTED_PROFILE_ERROR_MESSAGES": [...] }
- Break down the larger test cases into smaller, focused ones using
context
blocks:describe("User Creation", () => { context("Profile Management", () => { it("updates basic profile information") it("updates contact information") it("validates mandatory fields") }) })
- Consider using data-test attributes instead of IDs for more stable selectors:
-userCreationPage.clickElementById("addUserButton") +userCreationPage.clickElement("[data-test=add-user-button]")Would you like me to provide more detailed examples for any of these improvements?
cypress/e2e/patient_spec/PatientRegistration.cy.ts (3)
1-7
: LGTM! Consider grouping related constants.The new imports align well with the added patient transfer functionality. The utility function
generatePhoneNumber
is a good addition for test data generation.Consider grouping related constants into separate objects for better organization and maintainability. For example:
const PATIENT_DETAILS = { yearOfBirth: "2001", occupation: "Student", // ... other patient-specific constants }; const TRANSFER_DETAILS = { phoneNumber: "9849511866", facility: "Dummy Shifting Center", // ... other transfer-specific constants };
Line range hint
284-321
: Enhance transfer test assertions and error handling.While the test covers basic transfer scenarios, consider adding:
- Verification of patient data persistence after transfer
- More explicit assertions for the transfer state
- Error handling for edge cases
Add these assertions after the successful transfer:
// Verify patient data after transfer cy.get('[data-testid="patient-details"]').within(() => { cy.contains(patientTransferName); cy.contains(yearOfBirth); cy.contains(patientTransferFacility); }); // Verify transfer state cy.get('[data-testid="transfer-status"]') .should('exist') .and('contain', 'Transferred'); // Add error handling for network issues cy.intercept('POST', '**/transfer', { statusCode: 500, body: { error: 'Network error' } }).as('transferError'); // Verify error handling cy.get('[data-testid="error-message"]') .should('contain', 'Transfer failed');
Line range hint
42-43
: Consider data privacy best practices in tests.While using test data:
- Use clearly fake phone numbers (e.g., starting with 555)
- Mask PII in error messages and notifications
Example for error message:
// Before cy.verifyNotification( "Patient Dummy Patient 10 (Male) transferred successfully" ); // After cy.verifyNotification( "Patient *** (Male) transferred successfully" );Also applies to: 284-321
cypress/e2e/patient_spec/PatientLogUpdate.cy.ts (4)
Line range hint
8-38
: Consider extracting test data to fixturesThe test data (patient names, vital signs, etc.) is currently hardcoded as constants. Consider moving this data to Cypress fixtures for better maintainability and reusability.
Example structure:
// cypress/fixtures/patient-log-data.json { "patients": { "domiciliary": "Dummy Patient 11", "normal": "Dummy Patient 9" }, "vitalSigns": { "systolic": "149", "diastolic": "119" } }Then in the test:
let testData: any; before(() => { cy.fixture('patient-log-data.json').then((data) => { testData = data; }); });
Line range hint
51-297
: Enhance test robustness and coverageSeveral improvements could make the tests more reliable and comprehensive:
- The tests contain hardcoded waits (e.g.,
cy.wait(2000)
). Replace these with proper Cypress commands that wait for specific conditions.- Consider breaking down long test cases into smaller, focused ones.
- Add test coverage for error scenarios.
Example improvements:
// Instead of cy.wait(2000) cy.intercept('POST', '/api/daily-rounds').as('saveRounds'); cy.submitButton("Save"); cy.wait('@saveRounds'); // Breaking down tests it("should create a Progress log update", () => { // Setup setupPatientAndBed(); // Create log createBasicProgressLog(); // Verify verifyProgressLogCreated(); }); it("should edit a Progress log update", () => { // Edit and verify editAndVerifyProgressLog(); });Also consider adding these test cases:
it("should handle network errors when saving log update", () => { cy.intercept('POST', '/api/daily-rounds', { statusCode: 500, body: { error: 'Internal Server Error' } }); // Test error handling }); it("should validate invalid vital signs", () => { // Test input validation });
Line range hint
51-297
: Extract selectors to constants or data-testid attributesThe tests use various string selectors (e.g.,
#dailyround-entry
,#consultation-preview
). Consider:
- Using data-testid attributes for more reliable selection
- Extracting selectors to constants
Example:
// Constants file export const SELECTORS = { DAILY_ROUND_ENTRY: '[data-testid="daily-round-entry"]', CONSULTATION_PREVIEW: '[data-testid="consultation-preview"]' }; // Test file import { SELECTORS } from './constants'; // ... cy.get(SELECTORS.DAILY_ROUND_ENTRY)
Line range hint
299-301
: Add proper test data cleanupThe test suite only saves localStorage in afterEach but doesn't clean up created test data. Consider adding proper cleanup to maintain test isolation.
Example:
afterEach(() => { cy.saveLocalStorage(); // Clean up created test data cy.request({ method: 'DELETE', url: '/api/test-cleanup', body: { patientIds: [/* list of created patient IDs */], logIds: [/* list of created log IDs */] } }); });src/components/Facility/ConsultationDetails/index.tsx (3)
253-264
: Consider extracting camera feed visibility logicThe camera feed visibility check combines multiple conditions, making it harder to read and maintain.
Consider extracting this logic into a separate function:
+ const shouldShowCameraFeed = () => { + return ( + patientData.last_consultation?.id && + isCameraAttached && + CameraFeedPermittedUserTypes.includes(authUser.user_type) + ); + }; - {patientData.last_consultation?.id && - isCameraAttached && - CameraFeedPermittedUserTypes.includes( - authUser.user_type, - ) && ( + {shouldShowCameraFeed() && ( <Link href={`/facility/${patientData.facility}/patient/${patientData.id}/consultation/${patientData.last_consultation?.id}/feed`} className="btn btn-primary m-1 w-full hover:text-white" > Camera Feed </Link> )}
274-286
: Simplify discussion notes click handlerThe click handler for discussion notes uses a ternary operator which makes the logic less readable.
Consider simplifying the logic:
- onClick={() => - showPatientNotesPopup - ? navigate( - `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/notes`, - ) - : setShowPatientNotesPopup(true) - } + onClick={() => { + if (showPatientNotesPopup) { + navigate(`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/notes`); + return; + } + setShowPatientNotesPopup(true); + }}
212-421
: Consider breaking down the component into smaller piecesThe component has grown quite large with complex UI structure. Consider extracting some logical pieces into separate components:
- Header section with navigation
- Patient info section
- Tabs navigation section
This would improve:
- Code maintainability
- Readability
- Reusability
- Testing
src/common/constants.tsx (1)
Line range hint
1-1069
: Consider splitting constants into domain-specific modules.This file is quite large and contains constants from multiple domains. Consider splitting it into smaller, more focused modules like:
medical.constants.ts
for medical/healthcare related constantsfile.constants.ts
for file handling constantssystem.constants.ts
for system-wide constantsThis would improve maintainability and make the code more modular.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (25)
cypress/e2e/assets_spec/AssetHomepage.cy.ts
(1 hunks)cypress/e2e/assets_spec/AssetsCreation.cy.ts
(1 hunks)cypress/e2e/assets_spec/AssetsManage.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityCreation.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityHomepage.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityInventory.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityManage.cy.ts
(3 hunks)cypress/e2e/patient_spec/PatientBedManagement.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientFileUpload.ts
(1 hunks)cypress/e2e/patient_spec/PatientLogUpdate.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientPrescription.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientRegistration.cy.ts
(1 hunks)cypress/e2e/resource_spec/ResourcesHomepage.cy.ts
(1 hunks)cypress/e2e/users_spec/UsersCreation.cy.ts
(1 hunks)cypress/e2e/users_spec/UsersManage.cy.ts
(1 hunks)src/App.tsx
(1 hunks)src/Routers/AppRouter.tsx
(0 hunks)src/Utils/request/api.tsx
(0 hunks)src/common/constants.tsx
(1 hunks)src/components/Facility/ConsultationDetails/ConsultationContext.tsx
(1 hunks)src/components/Facility/ConsultationDetails/index.tsx
(5 hunks)src/components/Facility/FacilityConfigure.tsx
(2 hunks)src/components/Facility/FacilityHome.tsx
(2 hunks)
💤 Files with no reviewable changes (2)
- src/Routers/AppRouter.tsx
- src/Utils/request/api.tsx
✅ Files skipped from review due to trivial changes (5)
- cypress/e2e/assets_spec/AssetHomepage.cy.ts
- cypress/e2e/facility_spec/FacilityCreation.cy.ts
- cypress/e2e/facility_spec/FacilityInventory.cy.ts
- cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts
- cypress/e2e/resource_spec/ResourcesHomepage.cy.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/App.tsx
- src/components/Facility/FacilityHome.tsx
🔇 Additional comments (23)
cypress/e2e/patient_spec/PatientBedManagement.cy.ts (1)
1-4
: LGTM: Import changes are clean and well-structured.
The addition of PatientConsultationPage import follows the existing pattern and is properly organized with other page object imports.
src/components/Facility/ConsultationDetails/ConsultationContext.tsx (4)
1-11
: LGTM! Clean imports and well-defined base interface.
The imports are appropriate and the base interface ConsultationContextBase
is well-structured with proper typing.
46-48
: Type assertion in useState initialization.
This issue has been previously identified and the suggested fix is still applicable.
21-35
: 🛠️ Refactor suggestion
Consider adding type safety check for generic parameter.
The type assertion in the hook could potentially hide type mismatches if the generic type T
doesn't match the Provider's type.
Consider adding a type guard:
export const useConsultation = <T extends object = object>() => {
const context = useContext(ConsultationContext);
if (!context) {
throw new Error(
"'useConsultation' must be used within 'ConsultationProvider' only",
);
}
+ // Type guard to ensure T matches Provider's type
+ const isValidType = (ctx: unknown): ctx is ConsultationContextType<T> => {
+ return typeof ctx === 'object' && ctx !== null && 'setValue' in ctx;
+ };
+
+ if (!isValidType(context)) {
+ throw new Error('Type mismatch between hook and provider');
+ }
+
- return context as ConsultationContextType<T>;
+ return context;
};
69-69
: Verify PLUGIN_Component integration.
The PLUGIN_Component
is used without any validation or error handling. Consider adding error boundaries or prop validation to handle potential plugin loading failures gracefully.
src/components/Facility/FacilityConfigure.tsx (2)
Line range hint 1-165
: Core facility configuration logic remains robust
The component maintains its essential functionality with proper form validation, error handling, and state management.
11-11
: Verify plugin system setup
The import suggests a new plugin-based architecture. Let's verify the plugin system setup.
✅ Verification successful
Plugin system implementation verified and properly used
The import of PLUGIN_Component
is consistent with the established plugin architecture pattern in the codebase:
PLUGIN_Component
is properly exported fromPluginEngine.tsx
with correct typing- The usage pattern with
__name
prop is consistent across multiple components:- ExtendFacilityConfigure
- ExtendPatientInfoCard
- DoctorConnectButtons
- ConsultationContextEnabler
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the plugin system setup and its usage across the codebase
# Test 1: Check if PluginEngine is properly exported
rg -l "export.*PLUGIN_Component"
# Test 2: Check for other plugin usages to ensure consistent implementation
rg "__name=\"ExtendFacility"
Length of output: 174
Script:
#!/bin/bash
# Let's verify the plugin system implementation and usage pattern
# Check the PLUGIN_Component implementation
rg -A 5 "export.*PLUGIN_Component" src/PluginEngine.tsx
# Check how ExtendFacilityConfigure is being used in context
rg -B 2 -A 2 "__name=\"ExtendFacilityConfigure\"" src/components/Facility/FacilityConfigure.tsx
# Look for similar plugin patterns to verify consistency
rg "PLUGIN_Component.*__name"
Length of output: 831
cypress/e2e/assets_spec/AssetsCreation.cy.ts (1)
2-5
: LGTM! Clean import organization.
The imports are well-organized following the page object pattern, with the new AssetSearchPage properly integrated.
cypress/e2e/assets_spec/AssetsManage.cy.ts (1)
2-2
: LGTM! Import reordering doesn't affect functionality.
The reordering of import statements is a minor change that maintains the code's functionality while potentially improving readability.
Also applies to: 5-5
cypress/e2e/facility_spec/FacilityHomepage.cy.ts (2)
2-5
: LGTM! Import statements are properly organized.
The reordering of imports maintains functionality while improving code organization.
2-5
: Verify test stability after ABDM component removal.
Given that this PR removes ABDM-related components, let's verify that the imported page objects and their dependencies are unaffected.
✅ Verification successful
No stability concerns after ABDM component removal
After reviewing the page objects used in the facility homepage test, I can confirm that they are not impacted by the ABDM removal:
- All imported page objects exist and are accessible
- None of the page objects contain any ABDM-related functionality
- The page objects focus on core facility management features like creation, navigation, and basic operations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the imported page objects still exist and haven't been modified as part of ABDM removal
# Test 1: Check if the page objects exist
echo "Checking existence of page objects..."
fd -t f "FacilityCreation.ts|FacilityHome.ts|LoginPage.ts|ManageUserPage.ts|UserSearch.ts|AssetPagination.ts" pageobject/
# Test 2: Check for any ABDM-related code in these files that might affect the tests
echo "Checking for ABDM dependencies in page objects..."
rg -i "abdm|ayushman" $(fd -t f "FacilityCreation.ts|FacilityHome.ts|LoginPage.ts|ManageUserPage.ts|UserSearch.ts|AssetPagination.ts" pageobject/)
Length of output: 2721
Script:
#!/bin/bash
# Let's check the correct path for page objects in cypress
echo "Checking for correct cypress page object path..."
fd -t f "FacilityCreation.ts|FacilityHome.ts|LoginPage.ts|AssetPagination.ts" cypress/
# Check content of these files if found
echo "Checking content of page objects if they exist..."
for file in $(fd -t f "FacilityCreation.ts|FacilityHome.ts|LoginPage.ts|AssetPagination.ts" cypress/); do
echo "=== Content of $file ==="
cat "$file"
echo -e "\n"
done
Length of output: 19289
cypress/e2e/users_spec/UsersManage.cy.ts (2)
4-4
: LGTM! The import statement follows the established pattern.
The addition of UserPage
import aligns with the page object pattern used throughout the test suite and maintains consistency with other imports.
Line range hint 7-171
: Verify test coverage for UserPage methods.
The test suite effectively uses the UserPage
instance for user search operations. However, let's ensure all UserPage
methods are properly tested.
Run the following script to analyze test coverage:
✅ Verification successful
Let me gather more information about the UserPage class definition to compare available methods with their usage.
Let me search specifically for the UserPage class since the previous result showed ManageUserPage instead.
Now I have enough information to generate the final response. Comparing the UserPage class definition with its usage in tests:
All UserPage methods are adequately covered in tests
The test coverage analysis shows that:
- All methods in the UserPage class (found in UserSearch.ts) are being used across multiple test files
- The methods are tested in various scenarios:
- Basic user search functionality in UsersManage.cy.ts
- Advanced filtering in UsersHomepage.cy.ts
- Pagination controls in UsersHomepage.cy.ts
- User badge visibility in UsersCreation.cy.ts
- Filter operations in FacilityHomepage.cy.ts
The initial concern about test coverage for UserPage methods is unfounded as the test suite demonstrates comprehensive coverage of all available methods.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify UserPage method usage and test coverage
# Find all available UserPage methods
echo "Available UserPage methods:"
ast-grep --pattern 'class UserPage {
$$$
$method($_) {
$$$
}
$$$
}'
# Find current usage of UserPage methods in tests
echo -e "\nUserPage method usage in tests:"
rg "userPage\." cypress/e2e/
Length of output: 6590
Script:
#!/bin/bash
# Find the UserPage class definition
echo "UserPage class definition:"
fd -e ts -e js UserPage --exec cat {}
Length of output: 4420
Script:
#!/bin/bash
# Search for UserPage class definition with a more specific pattern
echo "UserPage class definition:"
ast-grep --pattern 'class UserPage {
$$$
}'
# Also try to find the file containing UserPage class
echo -e "\nFiles containing UserPage class:"
fd -e ts -e js -e tsx -e jsx -x grep -l "class UserPage"
Length of output: 8787
cypress/e2e/patient_spec/PatientPrescription.cy.ts (2)
3-3
: LGTM! Import statement correctly restored.
The import statement for PatientPrescription has been properly reactivated, which is essential for the test suite functionality.
Line range hint 1-168
: Verify test reliability after architectural changes.
Given the significant architectural changes in this PR (introduction of PubSubProvider and removal of ABDM components), we should verify that these test scenarios still accurately reflect the current application behavior.
Let's verify the test dependencies and potential impacts:
✅ Verification successful
Let me gather more specific information about the components and their interactions.
Based on the gathered information, I can now provide a final response:
Tests are independent of PubSub architectural changes
The test file PatientPrescription.cy.ts
and its dependencies (page objects) are isolated from the architectural changes:
- The tests interact with the application through Cypress commands and page objects that abstract the implementation details
- The page objects (
LoginPage
,PatientPage
,PatientPrescription
) use standard Cypress commands and don't depend on PubSub - The PubSub implementation is contained within the React application layer (
src/
directory) and doesn't affect the E2E test layer - No ABDM references were found in the test files or their dependencies
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining ABDM references that might affect these tests
# and verify the structure of components these tests interact with
# Check for any remaining ABDM references in the pageobject files
echo "Checking for ABDM references in pageobjects..."
rg -l "ABDM" "cypress/pageobject"
# Verify the structure of components these tests interact with
echo "Checking component structure..."
fd -e tsx -e ts "PatientPrescription|PubSubProvider" "src/"
Length of output: 267
Script:
#!/bin/bash
# Check the actual test dependencies and component structure
# Check imports and dependencies in the test file
echo "Checking imports in the test file..."
rg -p "import.*from" "cypress/e2e/patient_spec/PatientPrescription.cy.ts"
# Check the page objects being used
echo "Checking page object implementations..."
fd -t f "LoginPage.ts|PatientCreation.ts|PatientPrescription.ts" "cypress/pageobject" --exec cat {}
# Check for PubSub related code in the components
echo "Checking PubSub usage in components..."
rg -p "PubSub|publish|subscribe" "src/"
Length of output: 36486
cypress/e2e/users_spec/UsersCreation.cy.ts (1)
3-9
: LGTM! Import statements are properly organized.
The import statements are well-structured and the reintroduction of generatePhoneNumber
aligns with its usage in the test cases.
cypress/e2e/patient_spec/PatientRegistration.cy.ts (2)
Line range hint 89-100
: LGTM! Well-structured test setup.
The test suite follows Cypress best practices with proper:
- Login setup in the
before
hook - localStorage management between tests
- Clear URL navigation in
beforeEach
Line range hint 1-321
: Verify alignment with ABDM integration objectives.
The changes focus on patient registration and transfer functionality, but the PR title mentions "ABDM Plug FE". Please clarify if there are additional ABDM-specific changes planned or if this PR's scope has changed.
cypress/e2e/patient_spec/PatientLogUpdate.cy.ts (1)
5-5
: LGTM: Import statement correctly enables PatientLogupdate functionality
The uncommented import statement properly enables the PatientLogupdate page object for use in the test suite.
src/components/Facility/ConsultationDetails/index.tsx (2)
205-210
: LGTM: ConsultationProvider integration is well implemented
The ConsultationProvider is correctly placed and properly initialized with the consultation and patient data.
70-83
:
Critical: Previous review comment about modifying const object remains unaddressed
The current implementation still modifies a const object (TABS) within useEffect, which can lead to race conditions and unexpected behavior. This issue was previously flagged but hasn't been addressed.
Please implement the state-based solution as suggested in the previous review:
- const TABS = {
+ const defaultTabs = {
UPDATES: ConsultationUpdatesTab,
// ... other tabs
} as Record<string, React.FC<ConsultationTabProps>>;
+ const [tabs, setTabs] = useState<Record<string, React.FC<ConsultationTabProps>>>(defaultTabs);
useEffect(() => {
if (pluginTabs) {
- for (const [key, value] of Object.entries(pluginTabs)) {
- TABS[key] = value as React.FC<ConsultationTabProps>;
- }
+ setTabs(prev => ({
+ ...prev,
+ ...pluginTabs
+ }));
}
}, [pluginTabs]);
src/common/constants.tsx (2)
Line range hint 1-1024
: LGTM: Clean removal of ABDM-related constants.
The removal of ABDM_CONSENT_PURPOSE
and ABDM_HI_TYPE
constants is clean and consistent with the PR objectives of removing ABDM functionality.
Line range hint 1025-1069
: LGTM: Well-structured file handling constants.
The file handling constants (FILE_EXTENSIONS
, PREVIEWABLE_FILE_EXTENSIONS
, HEADER_CONTENT_TYPES
) are well-structured and use TypeScript's 'as const' assertion for type safety.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (7)
src/Utils/pubsubContext.tsx (3)
16-20
: Consider memoizing the subscribers state.The current implementation might cause unnecessary re-renders when the subscribers object changes. Consider using
useMemo
for complex state derivations or computations based on this state.
64-71
: Memoize the context value to prevent unnecessary re-renders.The context value object is recreated on every render, which could cause unnecessary re-renders in consuming components.
+ const contextValue = useMemo( + () => ({ subscribe, unsubscribe, publish, subscribers, setSubscribers }), + [subscribers] + ); return ( <PubSubContext.Provider - value={{ subscribe, unsubscribe, publish, subscribers, setSubscribers }} + value={contextValue} >
1-81
: Consider adding comprehensive testing and documentation.As this is a core communication mechanism:
- Add unit tests covering all edge cases (concurrent publishes, error handling, etc.)
- Add integration tests demonstrating typical usage patterns
- Document common patterns and best practices for using this PubSub system
- Consider adding TypeScript examples in the documentation
Would you like me to help create a test suite or documentation template?
src/components/Facility/ConsultationDetails/index.tsx (4)
Line range hint
56-84
: Consider optimizing tabs state initializationWhile the current implementation correctly addresses the const object modification issue, we can optimize the initial state to avoid an unnecessary state update when
pluginTabs
is available immediately.Consider this optimization:
- const [tabs, setTabs] = - useState<Record<string, React.FC<ConsultationTabProps>>>(defaultTabs); - const pluginTabs = useCareAppConsultationTabs(); + const pluginTabs = useCareAppConsultationTabs(); + const [tabs, setTabs] = useState<Record<string, React.FC<ConsultationTabProps>>>( + () => ({ ...defaultTabs, ...pluginTabs }) + ); useEffect(() => { if (pluginTabs) { setTabs((prev) => ({ ...prev, ...pluginTabs })); } }, [pluginTabs]);
205-210
: Consider adding error boundariesThe ConsultationProvider is properly implemented, but adding error boundaries would improve error handling for child components.
Consider implementing an error boundary component:
class ConsultationErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error: Error) { return { hasError: true }; } render() { if (this.state.hasError) { return <div>Something went wrong in the consultation view.</div>; } return this.props.children; } }Then wrap the provider:
+ <ConsultationErrorBoundary> <ConsultationProvider initialContext={{ consultation: consultationData, patient: patientData, }} > {/* ... */} </ConsultationProvider> + </ConsultationErrorBoundary>
253-264
: Extract camera feed visibility logicThe camera feed visibility logic is complex with multiple conditions. Consider extracting it into a separate function for better maintainability.
Consider this refactor:
+ const shouldShowCameraFeed = () => { + return ( + patientData.last_consultation?.id && + isCameraAttached && + CameraFeedPermittedUserTypes.includes(authUser.user_type) + ); + }; - {patientData.last_consultation?.id && - isCameraAttached && - CameraFeedPermittedUserTypes.includes( - authUser.user_type, - ) && ( + {shouldShowCameraFeed() && ( <Link href={`/facility/${patientData.facility}/patient/${patientData.id}/consultation/${patientData.last_consultation?.id}/feed`} className="btn btn-primary m-1 w-full hover:text-white" > Camera Feed </Link> )}
376-398
: Extract feed tab visibility logicThe feed tab visibility logic in the tab mapping is complex. Consider extracting it into a separate function for better readability.
Consider this refactor:
+ const shouldHideFeedTab = (tabKey: string) => { + if (tabKey !== "FEED") return false; + return ( + isCameraAttached === false || + consultationData?.discharge_date || + !consultationData?.current_bed?.bed_object?.id || + !CameraFeedPermittedUserTypes.includes(authUser.user_type) + ); + }; {keysOf(tabs).map((p) => { - if (p === "FEED") { - if ( - isCameraAttached === false || - consultationData?.discharge_date || - !consultationData?.current_bed?.bed_object?.id || - !CameraFeedPermittedUserTypes.includes(authUser.user_type) - ) - return null; - } + if (shouldHideFeedTab(p)) return null; return ( <Link key={p} className={tabButtonClasses(tab === p)} href={`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/${p.toLocaleLowerCase()}`} > {t(`CONSULTATION_TAB__${p}`)} </Link> ); })}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
src/Utils/pubsubContext.tsx
(1 hunks)src/components/Facility/ConsultationDetails/index.tsx
(7 hunks)
🔇 Additional comments (2)
src/Utils/pubsubContext.tsx (1)
73-81
: LGTM! Well-implemented custom hook.
The hook properly checks for context availability and provides a clear error message.
src/components/Facility/ConsultationDetails/index.tsx (1)
Line range hint 1-47
: LGTM! Clean import organization
The new imports are properly organized and the types are well-defined.
const subscribe = (topic: string, handler: Handler) => { | ||
setSubscribers((prev) => ({ | ||
...prev, | ||
[topic]: new Set([...(prev[topic] || []), handler]), | ||
})); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Optimize subscription handling and add validation.
The current implementation creates a new Set on each subscription and doesn't check for duplicate handlers.
Consider this optimization:
const subscribe = (topic: string, handler: Handler) => {
setSubscribers((prev) => {
+ const existing = prev[topic];
+ if (existing?.has(handler)) {
+ return prev; // Avoid duplicate handlers
+ }
return {
...prev,
- [topic]: new Set([...(prev[topic] || []), handler]),
+ [topic]: existing ? existing.add(handler) : new Set([handler]),
};
});
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const subscribe = (topic: string, handler: Handler) => { | |
setSubscribers((prev) => ({ | |
...prev, | |
[topic]: new Set([...(prev[topic] || []), handler]), | |
})); | |
}; | |
const subscribe = (topic: string, handler: Handler) => { | |
setSubscribers((prev) => { | |
const existing = prev[topic]; | |
if (existing?.has(handler)) { | |
return prev; // Avoid duplicate handlers | |
} | |
return { | |
...prev, | |
[topic]: existing ? existing.add(handler) : new Set([handler]), | |
}; | |
}); | |
}; |
const publish = (topic: string, message: unknown) => { | ||
if (!subscribers[topic]) { | ||
return; | ||
} | ||
|
||
subscribers[topic].forEach(async (handler) => { | ||
try { | ||
await handler(message); | ||
} catch (error) { | ||
console.error(`Handler failed for topic ${topic}:`, error); | ||
} | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider handling concurrent publishes and tracking completion.
The current implementation has two potential issues:
- Concurrent publishes might execute handlers in an unpredictable order
- No way to track when all handlers have completed
Consider this enhancement:
- const publish = (topic: string, message: unknown) => {
+ const publish = async (topic: string, message: unknown): Promise<boolean> => {
if (!subscribers[topic]) {
- return;
+ return true;
}
- subscribers[topic].forEach(async (handler) => {
- try {
- await handler(message);
- } catch (error) {
- console.error(`Handler failed for topic ${topic}:`, error);
- }
- });
+ const results = await Promise.allSettled(
+ Array.from(subscribers[topic]).map((handler) =>
+ handler(message).catch((error) => {
+ console.error(`Handler failed for topic ${topic}:`, error);
+ return false;
+ })
+ )
+ );
+
+ return results.every((result) =>
+ result.status === 'fulfilled' && result.value !== false
+ );
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const publish = (topic: string, message: unknown) => { | |
if (!subscribers[topic]) { | |
return; | |
} | |
subscribers[topic].forEach(async (handler) => { | |
try { | |
await handler(message); | |
} catch (error) { | |
console.error(`Handler failed for topic ${topic}:`, error); | |
} | |
}); | |
}; | |
const publish = async (topic: string, message: unknown): Promise<boolean> => { | |
if (!subscribers[topic]) { | |
return true; | |
} | |
const results = await Promise.allSettled( | |
Array.from(subscribers[topic]).map((handler) => | |
handler(message).catch((error) => { | |
console.error(`Handler failed for topic ${topic}:`, error); | |
return false; | |
}) | |
) | |
); | |
return results.every((result) => | |
result.status === 'fulfilled' && result.value !== false | |
); | |
}; |
https://github.com/ohcnetwork/care_abdm_fe
Resolves #8941
Summary by CodeRabbit
Release Notes
New Features
PubSubProvider
for enhanced event-driven communication across components.Removed Features
Bug Fixes
Documentation